ready to release

git-svn-id: https://svn.research-infrastructures.eu/d4science/gcube/trunk/portlets/user/share-updates@68368 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Massimiliano Assante 2013-01-26 19:02:51 +00:00
parent 1c16bf7897
commit e041f7c313
62 changed files with 3360 additions and 0 deletions

36
.classpath Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/share-updates-0.1.0-SNAPSHOT/WEB-INF/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/gwt"/>
<classpathentry including="**/*.java" kind="src" output="src/main/webapp/WEB-INF/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/share-updates-0.1.0-SNAPSHOT/WEB-INF/classes"/>
</classpath>

59
.project Normal file
View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>share-updates</name>
<comment>share-updates project</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
</natures>
</projectDescription>

15
.settings/.jsdtscope Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/webapp" />
<classpathentry kind="con"
path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER" />
<classpathentry kind="con"
path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true" />
</attributes>
</classpathentry>
<classpathentry kind="con"
path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary" />
<classpathentry kind="output" path="" />
</classpath>

View File

@ -0,0 +1,3 @@
#Thu Jun 16 10:18:26 CEST 2011
eclipse.preferences.version=1
filesCopiedToWebInfLib=

View File

@ -0,0 +1,6 @@
#Sat Jan 26 18:07:22 CET 2013
eclipse.preferences.version=1
jarsExcludedFromWebInfLib=
lastWarOutDir=/Users/massi/Documents/workspace/share-updates/target/share-updates-0.1.0-SNAPSHOT
warSrcDir=src/main/webapp
warSrcDirIsOutput=false

View File

@ -0,0 +1,5 @@
#Thu Jun 16 11:14:17 CEST 2011
eclipse.preferences.version=1
entryPointModules=
filesCopiedToWebInfLib=gwt-servlet.jar
gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy13YXIgc3JjL21haW4vd2ViYXBwXV0+PC9leHRyYS1hcmdzPjx2bS1hcmdzPjwhW0NEQVRBWy1YbXg1MTJtXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLmNvbXBhbnkuU29tZU1vZHVsZTwvZW50cnktcG9pbnQtbW9kdWxlPjwvZ3d0LWNvbXBpbGUtc2V0dGluZ3M+

View File

@ -0,0 +1,7 @@
#Sat Jan 26 18:07:22 CET 2013
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,9 @@
#Thu Sep 02 10:42:20 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@ -0,0 +1,5 @@
#Sat Jan 26 18:07:21 CET 2013
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="${module}">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/>
<property name="java-output-path" value="/${module}/target/www/WEB-INF/classes"/>
<property name="context-root" value="share-updates"/>
</wb-module>
</project-modules>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.jsdt.web" />
<installed facet="java" version="1.5" />
<installed facet="jst.web" version="2.3" />
<installed facet="wst.jsdt.web" version="1.0" />
</faceted-project>

View File

@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View File

@ -0,0 +1,9 @@
#Thu Sep 02 10:42:12 CEST 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gwt.eclipse.core.launch.gwtJUnit">
<stringAttribute key="com.google.gwt.eclipse.core.LOG_LEVEL" value="INFO"/>
<booleanAttribute key="com.google.gwt.eclipse.core.NOT_HEADLESS" value="false"/>
<stringAttribute key="com.google.gwt.eclipse.core.OUT_DIR" value="www-test"/>
<booleanAttribute key="com.google.gwt.eclipse.core.STANDARDS_MODE" value="false"/>
<stringAttribute key="com.google.gwt.eclipse.core.STYLE" value="OBFUSCATED"/>
<stringAttribute key="com.google.gwt.eclipse.core.WEB_MODE" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/share-updates/src/test/java/org/gcube/portlets/user/shareupdates/client/GwtTestShareUpdates.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gdt.eclipse.maven.mavenClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.gcube.portlets.user.shareupdates.client.GwtTestShareUpdates"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="share-updates"/>
</launchConfiguration>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="com.google.gwt.eclipse.core.launch.gwtJUnit">
<stringAttribute key="com.google.gwt.eclipse.core.LOG_LEVEL" value="INFO"/>
<booleanAttribute key="com.google.gwt.eclipse.core.NOT_HEADLESS" value="false"/>
<stringAttribute key="com.google.gwt.eclipse.core.OUT_DIR" value="www-test"/>
<booleanAttribute key="com.google.gwt.eclipse.core.STANDARDS_MODE" value="false"/>
<stringAttribute key="com.google.gwt.eclipse.core.STYLE" value="OBFUSCATED"/>
<stringAttribute key="com.google.gwt.eclipse.core.WEB_MODE" value="true"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/share-updates/src/test/java/org/gcube/portlets/user/shareupdates/client/GwtTestShareUpdates.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gdt.eclipse.maven.mavenClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.gcube.portlets.user.shareupdates.client.GwtTestShareUpdates"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="share-updates"/>
</launchConfiguration>

2
distro/INSTALL Normal file
View File

@ -0,0 +1,2 @@

7
distro/LICENSE Normal file
View File

@ -0,0 +1,7 @@
gCube System - License
------------------------------------------------------------
The gCube/gCore software is licensed as Free Open Source software conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
The software and documentation is provided by its authors/distributors "as is" and no expressed or
implied warranty is given for its use, quality or fitness for a particular case.

6
distro/MAINTAINERS Normal file
View File

@ -0,0 +1,6 @@
Mantainers
-------
* Massimiliano Assante (massimiliano.assante@isti.cnr.it), CNR Pisa,
Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo".

35
distro/README Normal file
View File

@ -0,0 +1,35 @@
The gCube System - Social Library
------------------------------------------------------------
This work is partially funded by the European Commission in the
context of the iMarine project (www.i-marine.eu), under the 1st call of FP7 IST priority.
Authors
-------
Massimiliano Assante
*
Version and Release Date
------------------------
Jan 2013
Description
-----------
Social networking Library
Download information
--------------------
Source code is available from SVN:
https://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/share-updates
Binaries can be downloaded from:
http://maven.research-infrastructures.eu/nexus/index.html#welcome
Documentation
-------------
Documentation is available on-line from the Projects Documentation Wiki:
Licensing
---------
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.

6
distro/changelog.xml Normal file
View File

@ -0,0 +1,6 @@
<ReleaseNotes>
<Changeset component="org.gcube.portlets.user.shareupdates.0-1-0"
date="2013-01-13">
<Change>First Release</Change>
</Changeset>
</ReleaseNotes>

48
distro/descriptor.xml Normal file
View File

@ -0,0 +1,48 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>servicearchive</id>
<formats>
<format>tar.gz</format>
</formats>
<baseDirectory>/</baseDirectory>
<fileSets>
<fileSet>
<directory>${distroDirectory}</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>README</include>
<include>LICENSE</include>
<include>INSTALL</include>
<include>MAINTAINERS</include>
<include>changelog.xml</include>
</includes>
<fileMode>755</fileMode>
<filtered>true</filtered>
</fileSet>
<fileSet>
<directory>target/apidocs</directory>
<outputDirectory>/${artifactId}/doc/api</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<fileMode>755</fileMode>
</fileSet>
</fileSets>
<files>
<file>
<source>${distroDirectory}/profile.xml</source>
<outputDirectory>./</outputDirectory>
<filtered>true</filtered>
</file>
<file>
<source>target/${build.finalName}.war</source>
<outputDirectory>/${artifactId}</outputDirectory>
</file>
<file>
<source>${distroDirectory}/svnpath.txt</source>
<outputDirectory>/${artifactId}</outputDirectory>
<filtered>true</filtered>
</file>
</files>
</assembly>

25
distro/profile.xml Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<Resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ID></ID>
<Type>Service</Type>
<Profile>
<Description>${description}</Description>
<Class>PortletUser</Class>
<Name>${artifactId}</Name>
<Version>${version}</Version>
<Packages>
<Software>
<Name>${artifactId}</Name>
<Version>${version}</Version>
<MavenCoordinates>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
</MavenCoordinates>
<Files>
<File>target/${build.finalName}.war</File>
</Files>
</Software>
</Packages>
</Profile>
</Resource>

1
distro/svnpath.txt Normal file
View File

@ -0,0 +1 @@
${scm.url}

281
pom.xml Normal file
View File

@ -0,0 +1,281 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>maven-parent</artifactId>
<groupId>org.gcube.tools</groupId>
<version>1.0.0</version>
<relativePath />
</parent>
<groupId>org.gcube.portlets.user</groupId>
<artifactId>share-updates</artifactId>
<packaging>war</packaging>
<version>0.1.0-SNAPSHOT</version>
<name>gCube Share Updates Portlet</name>
<description>
gCube Share Updates for exchanging updates with other users of VREs.
</description>
<scm>
<connection>scm:svn:http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId}</connection>
<developerConnection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId}</developerConnection>
<url>http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId}</url>
</scm>
<properties>
<!-- Convenience property to set the GWT version -->
<gwtVersion>2.4.0</gwtVersion>
<distroDirectory>distro</distroDirectory>
<!-- GWT needs at least java 1.6 -->
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<!-- This dependency is needed and is need on TOP to use GWT UI BInder
without old Xerces version of gCore complaining -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.sencha.gxt</groupId>
<artifactId>gxt</artifactId>
<version>2.2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.4.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>gcf</artifactId>
<version>[1.4.0,1.6.0]</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.portlets.user</groupId>
<artifactId>gcube-widgets</artifactId>
<version>1.4.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.portal</groupId>
<artifactId>custom-portal-handler</artifactId>
<version>1.2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.applicationsupportlayer</groupId>
<artifactId>aslcore</artifactId>
<version>3.2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google</groupId>
<artifactId>gwt-jsonmaker</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmllexer</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlcleaner</groupId>
<artifactId>htmlcleaner</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>net.sf.jtidy</groupId>
<artifactId>jtidy</artifactId>
<version>r938</version>
</dependency>
<dependency>
<groupId>net.eliasbalasis</groupId>
<artifactId>tibcopagebus4gwt</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>portal-service</artifactId>
<version>6.0.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.portlet</groupId>
<artifactId>portlet-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
<classifier>sources</classifier>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!-- Generate compiled stuff in the folder used for developing mode -->
<outputDirectory>${webappDirectory}/WEB-INF/classes</outputDirectory>
<plugins>
<!-- GWT Maven Plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.4.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<!-- <goal>test</goal> -->
</goals>
</execution>
</executions>
<!-- Plugin configuration. There are many available options, see gwt-maven-plugin
documentation at codehaus.org -->
<configuration>
<runTarget>Messages.html</runTarget>
<hostedWebapp>${webappDirectory}</hostedWebapp>
</configuration>
</plugin>
<!-- Copy static web files before executing gwt:run -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>
<webappDirectory>${webappDirectory}</webappDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<!-- SA Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<descriptors>
<descriptor>${distroDirectory}/descriptor.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>servicearchive</id>
<phase>install</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-profile</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target</outputDirectory>
<resources>
<resource>
<directory>${distroDirectory}</directory>
<filtering>true</filtering>
<includes>
<include>profile.xml</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,22 @@
package org.gcube.portlets.user.shareupdates.client;
import org.gcube.portal.databook.shared.ClientFeed;
import org.gcube.portal.databook.shared.FeedType;
import org.gcube.portal.databook.shared.PrivacyLevel;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portlets.user.shareupdates.shared.LinkPreview;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("shareupdateServlet")
public interface ShareUpdateService extends RemoteService {
ClientFeed share(String feedText, FeedType type, PrivacyLevel pLevel, String vreName, String linkTitle, String linkDesc, String url, String urlThumbnail, String host);
UserInfo getUserInfo();
LinkPreview checkLink(String linkToCheck);
}

View File

@ -0,0 +1,20 @@
package org.gcube.portlets.user.shareupdates.client;
import org.gcube.portal.databook.shared.ClientFeed;
import org.gcube.portal.databook.shared.FeedType;
import org.gcube.portal.databook.shared.PrivacyLevel;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portlets.user.shareupdates.shared.LinkPreview;
import com.google.gwt.user.client.rpc.AsyncCallback;
/**
* The async counterpart of <code>ShareUpdateService</code>.
*/
public interface ShareUpdateServiceAsync {
void share(String feedText, FeedType type, PrivacyLevel pLevel,
String vreName, String linkTitle, String linkDesc, String url,
String urlThumbnail, String host, AsyncCallback<ClientFeed> callback);
void getUserInfo(AsyncCallback<UserInfo> callback);
void checkLink(String linkToCheck, AsyncCallback<LinkPreview> callback);
}

View File

@ -0,0 +1,20 @@
package org.gcube.portlets.user.shareupdates.client;
import org.gcube.portlets.user.shareupdates.client.form.ShareUpdateForm;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class ShareUpdates implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
RootPanel.get("shareUpdateDiv").add(new ShareUpdateForm());
}
}

View File

@ -0,0 +1,95 @@
package org.gcube.portlets.user.shareupdates.client.form;
import java.util.ArrayList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.VerticalPanel;
public class ImageSwitcher extends Composite{
private ArrayList<String> imageUrls;
private VerticalPanel mainPanel = new VerticalPanel();
private HorizontalPanel controlPanel = new HorizontalPanel();
private Image image = new Image();
private HTML prev = new HTML(" << ");
private HTML label = new HTML("1 of 1");
private HTML next = new HTML(" >> ");
private int currentIndex = 0;
public ImageSwitcher() {
super();
image.setWidth("80px");
mainPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
mainPanel.setPixelSize(100, 100);
mainPanel.add(image);
controlPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
controlPanel.add(prev);
controlPanel.add(label);
controlPanel.add(next);
mainPanel.add(controlPanel);
prev.setStyleName("small-text-arrow");
label.setStyleName("small-text");
next.setStyleName("small-text-arrow");
initWidget(mainPanel);
next.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
if (imageUrls != null && currentIndex < imageUrls.size()) {
currentIndex++;
image.setUrl(imageUrls.get(currentIndex));
label.setHTML((currentIndex+1)+" of " + imageUrls.size());
}
}
});
prev.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
if (imageUrls != null && currentIndex > 0) {
currentIndex--;
image.setUrl(imageUrls.get(currentIndex));
label.setHTML((currentIndex+1)+" of " + imageUrls.size());
}
}
});
}
protected void setImages(ArrayList<String> imageUrls) {
this.imageUrls = imageUrls;
if (imageUrls.size() == 0) {
mainPanel.remove(controlPanel);
return;
}
image.setUrl(imageUrls.get(0));
GWT.log("images no. " + imageUrls.size());
if (imageUrls.size() < 2) {
prev.setVisible(false);
next.setVisible(false);
} else {
enableSwitch(imageUrls);
}
}
private void enableSwitch(ArrayList<String> imageUrls) {
label.setHTML("1 of " + imageUrls.size());
currentIndex = 0;
}
protected String getSelectedImageURL() {
return image.getUrl();
}
}

View File

@ -0,0 +1,22 @@
package org.gcube.portlets.user.shareupdates.client.form;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
public class LinkLoader extends Composite {
private static LinkLoaderUiBinder uiBinder = GWT
.create(LinkLoaderUiBinder.class);
interface LinkLoaderUiBinder extends UiBinder<Widget, LinkLoader> {
}
public LinkLoader() {
initWidget(uiBinder.createAndBindUi(this));
}
}

View File

@ -0,0 +1,8 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:HTMLPanel>
<div style="width:600px; height:25px; text-align:center; margin-left: 5px;" class="image-loader"></div>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,11 @@
package org.gcube.portlets.user.shareupdates.client.form;
import com.google.gwt.user.client.ui.SimplePanel;
/**
*
* @author massi
*
*/
public class LinkPlaceholder extends SimplePanel {
}

View File

@ -0,0 +1,83 @@
package org.gcube.portlets.user.shareupdates.client.form;
import org.gcube.portlets.user.shareupdates.shared.LinkPreview;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
public class LinkPreviewer extends Composite {
private static LinkPreviewUiBinder uiBinder = GWT
.create(LinkPreviewUiBinder.class);
interface LinkPreviewUiBinder extends UiBinder<Widget, LinkPreviewer> {
}
private ShareUpdateForm parent;
private LinkPreview toShow;
public LinkPreviewer(ShareUpdateForm parent, LinkPreview toShow) {
initWidget(uiBinder.createAndBindUi(this));
closeImage.setStyleName("su-closeImage");
closeImage.setTitle("Cancel");
this.parent = parent;
this.toShow = toShow;
titleArea.setHTML("<a class=\"link\" target=\"_blank\" href=\"" + toShow.getUrl() + "\">"+toShow.getTitle()+"</a> <span style=\"color: #333;\"> - " + toShow.getHost() + "</span>");
String url = toShow.getUrl();
urlText.setHTML((url.length() > 80) ? url.substring(0, 80)+"..." : url);
String desc = toShow.getDescription();
descText.setHTML((desc.length() > 256) ? desc.substring(0, 256)+"..." : desc);
switcher.setImages(toShow.getImageUrls());
}
@UiField HTML closeImage;
@UiField ImageSwitcher switcher;
@UiField
HTML titleArea;
@UiField
HTML urlText;
@UiField
HTML descText;
@UiField
CheckBox hideCheckBox;
public ImageSwitcher getSwitcher() {
return switcher;
}
@UiHandler("closeImage")
void onDeleteFeedClick(ClickEvent e) {
parent.cancelPreview();
}
@UiHandler("hideCheckBox")
void onClick(ClickEvent e) {
descText.setVisible(!hideCheckBox.getValue());
}
public String getLinkTitle() {
return toShow.getTitle();
}
public String getLinkDescription() {
return hideCheckBox.getValue() ? "" : toShow.getDescription();
}
public String getUrl() {
return toShow.getUrl();
}
public String getHost() {
return toShow.getHost();
}
public String getUrlThumbnail() {
return switcher.getSelectedImageURL();
}
}

View File

@ -0,0 +1,35 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:m="urn:import:org.gcube.portlets.user.shareupdates.client.form">
<ui:style>
.important {
font-weight: bold;
}
</ui:style>
<g:HTMLPanel>
<table class="link-previewer">
<tr>
<td width="60px;" align="middle">
<m:ImageSwitcher ui:field="switcher"></m:ImageSwitcher>
</td>
<td width="100%" valign="TOP">
<div class="link-title">
<g:HTML styleName="" ui:field="titleArea" />
</div>
<div class="link-url">
<g:HTML styleName="" ui:field="urlText" />
</div>
<div class="link-desc">
<g:HTML styleName="" ui:field="descText" />
<div class="hide-description">
<g:CheckBox ui:field="hideCheckBox">Hide Description</g:CheckBox>
</div>
</div>
</td>
<td valign="top" class="linkpreview-bgcolor">
<g:HTML height="15px" width="15px" ui:field="closeImage"></g:HTML>
</td>
</tr>
</table>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,66 @@
/**
*
*/
package org.gcube.portlets.user.shareupdates.client.form;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.TextArea;
/**
* @author massi
*
*/
public class MyTextArea extends TextArea {
/**
*
*/
public MyTextArea() {
sinkEvents(Event.ONPASTE);
sinkEvents(Event.ONCONTEXTMENU);
}
/**
* @param element
*/
public MyTextArea(Element element) {
super(element);
}
/**
* paste event overridden
*/
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (event.getTypeInt()) {
case Event.ONPASTE: {
final String before = getText();
GWT.log("BEFORE:" + before);
Timer t = new Timer() {
@Override
public void run() {
String toCheck = getText().replaceAll(before, "");
ShareUpdateForm.get().checkLink(toCheck);
}
};
t.schedule(100);
break;
}
case Event.ONCONTEXTMENU: {
removeSampleText();
break;
}
}
}
protected void removeSampleText() {
if (getText().equals(ShareUpdateForm.SHARE_UPDATE_TEXT) || getText().equals(ShareUpdateForm.ERROR_UPDATE_TEXT) ) {
setText("");
addStyleName("dark-color");
removeStyleName("error");
}
}
}

View File

@ -0,0 +1,295 @@
package org.gcube.portlets.user.shareupdates.client.form;
import net.eliasbalasis.tibcopagebus4gwt.client.PageBusAdapter;
import net.eliasbalasis.tibcopagebus4gwt.client.PageBusAdapterException;
import org.gcube.portal.databook.shared.ClientFeed;
import org.gcube.portal.databook.shared.ClientFeed.ClientFeedJsonizer;
import org.gcube.portal.databook.shared.FeedType;
import org.gcube.portal.databook.shared.PrivacyLevel;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portlets.user.shareupdates.client.ShareUpdateService;
import org.gcube.portlets.user.shareupdates.client.ShareUpdateServiceAsync;
import org.gcube.portlets.user.shareupdates.shared.LinkPreview;
import org.jsonmaker.gwt.client.Jsonizer;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Widget;
/**
*
* @author Massimiliano Assante
* @version 1.2 Nov 2012
*
*/
public class ShareUpdateForm extends Composite {
/**
* Create a remote service proxy to talk to the server-side Greeting service.
*/
private final ShareUpdateServiceAsync shareupdateService = GWT
.create(ShareUpdateService.class);
final PageBusAdapter pageBusAdapter = new PageBusAdapter();
protected final static String SHARE_UPDATE_TEXT = "Share an update or paste a link";
protected final static String ERROR_UPDATE_TEXT = "Looks like empty to me!";
private final static String LISTBOX_LEVEL = " - ";
public static final String loading = GWT.getModuleBaseURL() + "../images/avatarLoader.gif";
public static final String avatar_default = GWT.getModuleBaseURL() + "../images/Avatar_default.png";
private static ShareUpdateFormUiBinder uiBinder = GWT
.create(ShareUpdateFormUiBinder.class);
private LinkPreviewer myLinkPreviewer;
interface ShareUpdateFormUiBinder extends UiBinder<Widget, ShareUpdateForm> {
}
private static ShareUpdateForm singleton;
public static ShareUpdateForm get() {
return singleton;
}
UserInfo myUserInfo;
public ShareUpdateForm() {
initWidget(uiBinder.createAndBindUi(this));
singleton = this;
avatarImage.setUrl(loading);
shareTextArea.setText(SHARE_UPDATE_TEXT);
shareupdateService.getUserInfo(new AsyncCallback<UserInfo>() {
public void onFailure(Throwable caught) {
avatarImage.setSize("60px", "60px");
avatarImage.setUrl(avatar_default);
}
public void onSuccess(UserInfo user) {
myUserInfo = user;
avatarImage.getElement().getParentElement().setAttribute("href", user.getAccountURL());
avatarImage.setSize("60px", "60px");
avatarImage.setUrl(user.getAvatarId());
if (myUserInfo.getOwnVREs().size() > 1){
privacyLevel.addItem("My VREs", PrivacyLevel.VRES.toString());
for (String vreId : myUserInfo.getOwnVREs().keySet())
privacyLevel.addItem(LISTBOX_LEVEL + myUserInfo.getOwnVREs().get(vreId), vreId);
}
else if (myUserInfo.getOwnVREs().size() == 1)
for (String vreId : myUserInfo.getOwnVREs().keySet())
privacyLevel.addItem(LISTBOX_LEVEL + myUserInfo.getOwnVREs().get(vreId), vreId);
privacyLevel.addItem("My Connections", PrivacyLevel.CONNECTION.toString());
if (user.isAdmin())
privacyLevel.addItem("Anyone", PrivacyLevel.PORTAL.toString());
}
});
}
@UiField
LinkPlaceholder preview;
@UiField
Button submitButton;
@UiField
Image avatarImage;
@UiField MyTextArea shareTextArea;
@UiField ListBox privacyLevel = new ListBox(false);
@UiHandler("shareTextArea")
void onShareUpdateClick(ClickEvent e) {
shareTextArea.removeSampleText();
}
@UiHandler("submitButton")
void onClick(ClickEvent e) {
shareupdateService.getUserInfo(new AsyncCallback<UserInfo>() {
public void onFailure(Throwable caught) {
Window.alert("Ops! we encountered some problems delivering your message, server is not responding, please try again in a short while.");
}
public void onSuccess(UserInfo result) {
if (result.getUsername().equals("test.user")) {
Window.alert("Your session has expired, please log out and login again");
return;
}
myUserInfo = result;
String toShare = shareTextArea.getText().trim();
if (toShare.equals(SHARE_UPDATE_TEXT) || toShare.equals(ERROR_UPDATE_TEXT) || toShare.equals("")) {
shareTextArea.addStyleName("error");
shareTextArea.setText(ERROR_UPDATE_TEXT);
return;
}
//then you can post
postTweet(toShare);
}
});
}
/**
*
* @param textToPost
*/
private void postTweet(String textToPost) {
String toShare = escapeHtml(textToPost);
if (! checkTextLength(toShare)) {
Window.alert("We found a single word containing more than 50 chars and it's not a link, is it meaningful?");
return;
}
submitButton.setEnabled(false);
shareTextArea.setEnabled(false);
String vreId = "";
if (getPrivacyLevel() == PrivacyLevel.SINGLE_VRE) {
vreId = privacyLevel.getValue(privacyLevel.getSelectedIndex());
}
String linkTitle = "";
String linkDescription = "";
String linkUrl = "";
String linkUrlThumbnail = "";
String linkHost = "";
if (myLinkPreviewer != null) {
linkTitle = myLinkPreviewer.getLinkTitle();
linkDescription = myLinkPreviewer.getLinkDescription();
linkUrl = myLinkPreviewer.getUrl();
linkUrlThumbnail = myLinkPreviewer.getUrlThumbnail();
linkHost = myLinkPreviewer.getHost();
}
shareupdateService.share(toShare, FeedType.TWEET, getPrivacyLevel(), vreId, linkTitle, linkDescription, linkUrl, linkUrlThumbnail, linkHost, new AsyncCallback<ClientFeed>() {
public void onFailure(Throwable caught) {
submitButton.setEnabled(true);
shareTextArea.setEnabled(true);
shareTextArea.setText(SHARE_UPDATE_TEXT);
preview.clear();
myLinkPreviewer = null;
}
public void onSuccess(ClientFeed feed) {
submitButton.setEnabled(true);
shareTextArea.setEnabled(true);
shareTextArea.setText(SHARE_UPDATE_TEXT);
preview.clear();
myLinkPreviewer = null;
if (feed == null)
Window.alert("Ops! we encountered some problems delivering your message, please try again in a short while.");
else {
// publish a message with the refresh notification
try {
pageBusAdapter.PageBusPublish("org.gcube.portal.databook.shared", feed, (Jsonizer)GWT.create(ClientFeedJsonizer.class));
} catch (PageBusAdapterException ex) {
GWT.log(ex.getMessage());
}
}
}
});
}
private PrivacyLevel getPrivacyLevel() {
String selected = privacyLevel.getValue(privacyLevel.getSelectedIndex());
if (selected.compareTo(PrivacyLevel.CONNECTION.toString()) == 0)
return PrivacyLevel.CONNECTION;
else if (selected.compareTo(PrivacyLevel.VRES.toString()) == 0)
return PrivacyLevel.VRES;
else if (selected.compareTo(PrivacyLevel.PRIVATE.toString()) == 0)
return PrivacyLevel.PRIVATE;
else if (selected.compareTo(PrivacyLevel.PORTAL.toString()) == 0)
return PrivacyLevel.PORTAL;
else
return PrivacyLevel.SINGLE_VRE;
}
/**
* Escape an html string. Escaping data received from the client helps to
* prevent cross-site script vulnerabilities.
*
* @param html the html string to escape
* @return the escaped string
*/
private String escapeHtml(String html) {
if (html == null) {
return null;
}
return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
.replaceAll(">", "&gt;");
}
/**
* called when pasting a possible link
* @param linkToCheck
*/
protected void checkLink(String textToCheck) {
if (myLinkPreviewer == null) {
String [] parts = textToCheck.split("\\s");
// Attempt to convert each item into an URL.
for( String item : parts ) {
if (item.startsWith("http")) {
preview.add(new LinkLoader());
//GWT.log("It's http link:" + linkToCheck);
shareupdateService.checkLink(textToCheck, new AsyncCallback<LinkPreview>() {
public void onFailure(Throwable caught) {
preview.clear();
}
public void onSuccess(LinkPreview result) {
preview.clear();
if (result != null)
addPreview(result);
}
});
break;
}
}
} else {
Window.alert("You cannot post two links, please remove the previous one first.");
}
}
/**
* called when pasting. it tries to avoid pasting long non spaced strings
* @param linkToCheck
*/
private boolean checkTextLength(String textToCheck) {
String [] parts = textToCheck.split("\\s");
// check the length of tokens
for( String item : parts ) {
if (! item.startsWith("http")) { //url are accepted as they can be trunked
if (item.length() > 50) {
return false;
}
}
}
return true;
}
/**
* add the link preview in the view
* @param result
*/
private void addPreview(LinkPreview result) {
myLinkPreviewer = new LinkPreviewer(this, result);
preview.add(myLinkPreviewer);
}
/**
*
*/
protected void cancelPreview() {
preview.clear();
myLinkPreviewer = null;
}
}

View File

@ -0,0 +1,48 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:m="urn:import:org.gcube.portlets.user.shareupdates.client.form">
<ui:style>
.important {
font-weight: bold;
}
</ui:style>
<g:HTMLPanel>
<table class="shareContainer">
<tr>
<td width="60px;" align="middle">
<a href="">
<g:Image title="Edit Profile Picture" styleName="member-photo"
url="" ui:field="avatarImage" width="60" height="60" />
</a>
</td>
<td>
<div class="shareContainer-in">
<m:MyTextArea styleName="post-message" ui:field="shareTextArea" />
</div>
</td>
</tr>
</table>
<m:LinkPlaceholder ui:field="preview"></m:LinkPlaceholder>
<table class="toolsContainer">
<tr>
<td valign="middle" width="50%">
<div style="text-align: left; padding-top: 2px; color: #777;">
privacy level:
<g:ListBox styleName="wizardListbox" ui:field="privacyLevel" />
</div>
</td>
<td valign="middle"></td>
<td valign="middle">
<div class="buttonDiv">
<!-- <g:Button styleName="wizardButton" ui:field="attachButton" -->
<!-- text="Attach a Link" /> -->
<g:Button ui:field="submitButton" width="90px" text="Share" />
</div>
</td>
</tr>
</table>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -0,0 +1,564 @@
package org.gcube.portlets.user.shareupdates.server;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.validator.routines.UrlValidator;
import org.gcube.application.framework.core.session.ASLSession;
import org.gcube.application.framework.core.session.SessionManager;
import org.gcube.common.core.utils.logging.GCUBEClientLog;
import org.gcube.portal.custom.communitymanager.OrganizationsUtil;
import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper;
import org.gcube.portal.databook.server.DBCassandraAstyanaxImpl;
import org.gcube.portal.databook.server.DatabookStore;
import org.gcube.portal.databook.shared.ClientFeed;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.FeedType;
import org.gcube.portal.databook.shared.PrivacyLevel;
import org.gcube.portal.databook.shared.UserInfo;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
import org.gcube.portlets.user.shareupdates.client.ShareUpdateService;
import org.gcube.portlets.user.shareupdates.server.metaseeker.MetaSeeker;
import org.gcube.portlets.user.shareupdates.server.opengraph.OpenGraph;
import org.gcube.portlets.user.shareupdates.shared.LinkPreview;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayGroupManager;
import org.gcube.vomanagement.usermanagement.model.GroupModel;
import org.htmlparser.beans.StringBean;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Tidy;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.Organization;
import com.liferay.portal.model.Role;
import com.liferay.portal.model.User;
import com.liferay.portal.model.UserModel;
import com.liferay.portal.service.OrganizationLocalServiceUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.theme.ThemeDisplay;
import com.sun.net.ssl.HttpsURLConnection;
/**
* The server side implementation of the RPC service.
*/
@SuppressWarnings("serial")
public class ShareUpdateServiceImpl extends RemoteServiceServlet implements ShareUpdateService {
/**
*
*/
private static final String ADMIN_ROLE = "Administrator";
/**
*
*/
private static GCUBEClientLog _log = new GCUBEClientLog(ShareUpdateServiceImpl.class);
/**
* The store interface
*/
private DatabookStore store;
/**
* used for debugging in eclipse
*/
private boolean withinPortal = false;
/**
* connect to cassandra at startup
*/
public void init() {
store = new DBCassandraAstyanaxImpl();
}
public void destroy() {
store.closeConnection();
}
/**
* the current ASLSession
* @return the session
*/
private ASLSession getASLSession() {
String sessionID = this.getThreadLocalRequest().getSession().getId();
String user = (String) this.getThreadLocalRequest().getSession().getAttribute(ScopeHelper.USERNAME_ATTRIBUTE);
if (user == null) {
_log.warn("USER IS NULL setting test.user and Running OUTSIDE PORTAL");
user = "test.user";
//user = "massimiliano.assante";
withinPortal = false;
}
else {
withinPortal = true;
}
System.out.println("SessionID = " + sessionID);
return SessionManager.getInstance().getASLSession(sessionID, user);
}
/**
*
*/
public ClientFeed share(String feedText, FeedType feedType, PrivacyLevel pLevel, String vreId, String linkTitle,
String linkDesc, String url, String urlThumbnail, String host) {
String escapedFeedText = escapeHtml(feedText);
String username = getASLSession().getUsername();
String email = username+"@isti.cnr.it";
String fullName = username+" FULL";
String thumbnailURL = "images/Avatar_default.png";
if (withinPortal) {
try {
UserInfo user = getUserFromSession();
email = user.getEmailaddress();
fullName = user.getFullName();
thumbnailURL = user.getAvatarId();
} catch (Exception e) {
e.printStackTrace();
}
}
Feed toShare = new Feed(UUID.randomUUID().toString(), feedType, username, new Date(),
"", url, urlThumbnail, transformUrls(escapedFeedText), pLevel, fullName, email, thumbnailURL, linkTitle, linkDesc, host);
_log.trace("Attempting to save Feed with text: " + escapedFeedText + " Level: " + pLevel);
boolean result = store.saveUserFeed(toShare);
//need to put the feed into VRES Timeline too
if (pLevel == PrivacyLevel.VRES) {
_log.trace("PrivacyLevel was set to VRES attempting to write onto User's VRES Timelines");
for (GroupModel vre : getUserVREs(username)) {
String vreScope = getScopeByOrganizationId(vre.getGroupId());
_log.trace("Attempting to write onto " + vreScope);
try {
store.saveFeedToVRETimeline(toShare.getKey(), vreScope);
} catch (FeedIDNotFoundException e) {
_log.error("Error writing onto VRES Time Line" + vreScope);
} //save the feed
_log.trace("Success writing onto " + vreScope);
}
} //share on a single VRE Timeline
//receives a VreId(groupId) get the scope from the groupId
else if (pLevel == PrivacyLevel.SINGLE_VRE && vreId != null && vreId.compareTo("") != 0) {
String vreScope = getScopeByOrganizationId(vreId);
_log.trace("Attempting to write onto " + vreScope);
try {
store.saveFeedToVRETimeline(toShare.getKey(), vreScope);
} catch (FeedIDNotFoundException e) {
_log.error("Error writing onto VRES Time Line" + vreScope);
} //save the feed
_log.trace("Success writing onto " + vreScope);
}
if (!result) return null;
ClientFeed cf = new ClientFeed(toShare.getKey(), toShare.getType().toString(), username, toShare.getUri(),
replaceAmpersand(toShare.getDescription()), fullName, email, thumbnailURL, toShare.getLinkTitle(), toShare.getLinkDescription(),
toShare.getUriThumbnail(), toShare.getLinkHost());
return cf;
}
private UserInfo getUserFromSession() {
return (UserInfo) getASLSession().getAttribute(UserInfo.USER_INFO_ATTR);
}
private void setUserInSession(UserInfo user) {
getASLSession().setAttribute(UserInfo.USER_INFO_ATTR, user);
}
private String replaceAmpersand(String toReplace) {
String toReturn = toReplace.replaceAll("&amp;", "&");
return toReturn;
}
/**
* utilty method that convert a url ina text in a clickable url by the browser
* and if the user has just pasted a link, converts the link in: shared a link
* @param feedText
* @return the text with the clickable url in it
*/
public String transformUrls(String feedText) {
StringBuilder sb = new StringBuilder();
// separate input by spaces ( URLs have no spaces )
String [] parts = feedText.split("\\s");
// Attempt to convert each item into an URL.
for (int i = 0; i < parts.length; i++) {
if (parts[i].startsWith("http")) {
try {
URL url = new URL(parts[i]);
if (i == 0 && parts.length == 1) //then he shared just a link
return sb.append("<span style=\"color:gray; font-size:12px;\">shared </span><a class=\"link\" href=\"").append(url).append("\" target=\"_blank\">").append("a link.").append("</a> ").toString();
// If possible then replace with anchor...
sb.append("<a class=\"link\" style=\"font-size:14px;\" href=\"").append(url).append("\" target=\"_blank\">").append(url).append("</a> ");
} catch (MalformedURLException e) {
// If there was an URL then it's not valid
_log.error("MalformedURLException returning... ");
return feedText;
}
} else {
sb.append(parts[i]);
sb.append(" ");
}
}
return sb.toString();
}
public UserInfo getUserInfo() {
try {
String username = getASLSession().getUsername();
String email = username+"@isti.cnr.it";
String fullName = username+" FULL";
String thumbnailURL = "images/Avatar_default.png";
if (withinPortal) {
getUserVREs(username);
UserModel user = UserLocalServiceUtil.getUserByScreenName(OrganizationsUtil.getCompany().getCompanyId(), username);
thumbnailURL = "/image/user_male_portrait?img_id="+user.getPortraitId();
fullName = user.getFirstName() + " " + user.getLastName();
email = user.getEmailAddress();
ThemeDisplay themeDisplay = (ThemeDisplay) this.getThreadLocalRequest().getSession().getAttribute(WebKeys.THEME_DISPLAY);
String accountURL = themeDisplay.getURLMyAccount().toString();
HashMap<String, String> vreNames = getUserVreNames(username);
UserInfo toReturn = new UserInfo(username, fullName, thumbnailURL, user.getEmailAddress(), accountURL, true, isAdmin(), vreNames);
setUserInSession(toReturn);
return toReturn;
}
else {
_log.info("Returning test USER");
HashMap<String, String> fakeVreNames = new HashMap<String, String>();
fakeVreNames.put("1","devVRE");
// fakeVreNames.put("2", "devNext");
return new UserInfo(getASLSession().getUsername(), fullName, thumbnailURL, email, "fakeAccountUrl", true, false, fakeVreNames);
}
} catch (Exception e) {
e.printStackTrace();
}
return new UserInfo();
}
/**
* return the id as key and the names as value of the vre a user is subscribed to
* @param username
* @return the id as key and the names as value of the vre a user is subscribed to
*/
private HashMap<String, String> getUserVreNames(String username) {
HashMap<String, String> toReturn = new HashMap<String, String>();
for (GroupModel vre : getUserVREs(username)) {
toReturn.put(vre.getGroupId(), vre.getGroupName());
}
return toReturn;
}
/**
* tell if the user is a portal administrator or not
* @param username
* @return true if is admin
* @throws SystemException
* @throws PortalException
*/
private boolean isAdmin() throws PortalException, SystemException {
User currUser = OrganizationsUtil.validateUser(getASLSession().getUsername());
List<Organization> organizations = OrganizationLocalServiceUtil.getOrganizations(0, OrganizationLocalServiceUtil.getOrganizationsCount());
Organization rootOrganization = null;
for (Organization organization : organizations) {
if (organization.getName().equals(OrganizationsUtil.getRootOrganizationName() ) ) {
rootOrganization = organization;
break;
}
}
try {
_log.trace("root: " + rootOrganization.getName() );
return (hasRole(ADMIN_ROLE, rootOrganization.getName(), currUser));
}
catch (NullPointerException e) {
_log.error("Cannot find root organziation, please check gcube-data.properties file in $CATALINA_HOME/conf folder");
return false;
}
}
/**
*
* @param rolename
* @param organizationName
* @param user
* @return
* @throws SystemException
*/
private boolean hasRole(String rolename, String organizationName, User user) throws SystemException {
for (Role role : user.getRoles())
if (role.getName().compareTo(rolename) == 0 )
return true;
return false;
}
/**
*
* @param username
* @return
*/
private ArrayList<GroupModel> getUserVREs(String username) {
ArrayList<GroupModel> toReturn = new ArrayList<GroupModel>();
User currUser;
try {
GroupManager gm = new LiferayGroupManager();
currUser = OrganizationsUtil.validateUser(username);
for (Organization org : currUser.getOrganizations())
if (gm.isVRE(org.getOrganizationId()+"")) {
GroupModel toAdd = gm.getGroup(""+org.getOrganizationId());
toReturn.add(toAdd);
}
} catch (Exception e) {
_log.error("Failed reading User VREs for : " + username);
e.printStackTrace();
return toReturn;
}
return toReturn;
}
private String getScopeByOrganizationId(String vreid) {
GroupManager gm = new LiferayGroupManager();
try {
return gm.getScope(vreid);
} catch (Exception e) {
_log.error("Could not find a scope for this VREid: " + vreid);
return null;
}
}
/**
* Escape an html string. Escaping data received from the client helps to
* prevent cross-site script vulnerabilities.
*
* @param html the html string to escape
* @return the escaped string
*/
private String escapeHtml(String html) {
if (html == null) {
return null;
}
return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
.replaceAll(">", "&gt;");
}
/**
* utilty method that extract an url ina text
* @param feedText
* @return the text with the clickable url in it
*/
public String extractURL(String feedText) {
// separate input by spaces ( URLs have no spaces )
String [] parts = feedText.split("\\s");
// Attempt to convert each item into an URL.
for( String item : parts ) {
if (item.startsWith("http")) {
try {
new URL(item);
return item;
} catch (MalformedURLException e) {
// If there was an URL then it's not valid
_log.error("MalformedURLException returning... ");
return null;
}
}
}
return null;
}
/**
* tries the following in the indicated order for Populating the Link preview
* Open Graph protocol
* Meta "title" and "description" tags
* Best guess from page content (not recommended)
*
* Schema.org microdata <-- This is still a TODO
*/
public LinkPreview checkLink(String linkToCheck) {
LinkPreview toReturn = null;
_log.info("to check " + linkToCheck);
//look for a url in text
linkToCheck = extractURL(linkToCheck);
if (linkToCheck == null)
return null; //no url
String[] schemes = {"http","https"};
UrlValidator urlValidator = new UrlValidator(schemes);
if (! urlValidator.isValid(linkToCheck)) {
_log.warn("url is NOT valid, returning nothing");
return null;
}
_log.debug("url is valid");
URL pageURL;
URLConnection siteConnection = null;
try {
pageURL = new URL(linkToCheck);
if (pageURL.getProtocol().equalsIgnoreCase("https")) {
System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
trustAllHTTPSConnections();
siteConnection = (HttpsURLConnection) pageURL.openConnection();
}
else
siteConnection = (HttpURLConnection) pageURL.openConnection();
} catch (MalformedURLException e) {
_log.error("url is not valid");
return null;
} catch (IOException e) {
_log.error("url is not reachable");
return null;
}
String title;
String description;
ArrayList<String> imageUrls = new ArrayList<String>();
//get the host from the url
String host = pageURL.getHost().replaceAll("www.", "");
//try openGraph First
OpenGraph ogLink = null;
try {
ogLink = new OpenGraph(linkToCheck, true, siteConnection);
if (ogLink == null || ogLink.getContent("title") == null) {
//there is no OpenGraph for this link
_log.info("No OpenGraph Found, going Best guess from page content") ;
toReturn = getInfoFromHTML(pageURL, linkToCheck, host);
} else {
//there is OpenGraph
title = ogLink.getContent("title");
description = (ogLink.getContent("description") != null) ? ogLink.getContent("description") : "";
description = ((description.length() > 256) ? description.substring(0, 256)+"..." : description);
//look for the imagem ask the guesser if not present
if (ogLink.getContent("image") != null)
imageUrls.add(ogLink.getContent("image"));
else {
ArrayList<String> images = getImagesFromHTML(pageURL);
if (! images.isEmpty())
imageUrls = images;
}
toReturn = new LinkPreview(title, description, linkToCheck, host, imageUrls);
return toReturn;
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return toReturn;
}
/**
* get all the image urls from an HTML page up to 15
* @param pageURL the url
* @return a list of image url
* @throws IOException
*/
private ArrayList<String> getImagesFromHTML(URL pageURL) throws IOException {
ArrayList<String> toReturn = new ArrayList<String>();
InputStream input = pageURL.openStream();
try {
Document document = new Tidy().parseDOM(input, null);
NodeList imgs = document.getElementsByTagName("img");
int upTo = (imgs.getLength() > 15) ? 15 : imgs.getLength();
for (int i = 0; i < upTo; i++) {
System.out.println(i);
toReturn.add(imgs.item(i).getAttributes().getNamedItem("src").getNodeValue());
}
}catch (NullPointerException e) {
_log.error("Error parsing HTML for images, malformed HTML returning what I found so far ... ");
return toReturn;
}
return toReturn;
}
/**
* to use when OpenGraph is not available, Tries Metadata first, then Best guess from page content
* @param pageUrl
* @param link
* @param host
* @return a LinPreview object instance filled with the extracted information
* @throws IOException
*/
private LinkPreview getInfoFromHTML(URL pageUrl, String link, String host) throws Exception {
LinkPreview toReturn = null;
String title = "";
String description = "";
InputStream input = pageUrl.openStream();
Document document = new Tidy().parseDOM(input, null);
NodeList titles = document.getElementsByTagName("title");
if (titles != null && titles.getLength()>0) {
if (titles.item(0).getFirstChild() == null || titles.item(0).getFirstChild().getNodeValue() == null) {
_log.error("[MANUAL-PARSE] Something wrong with the title element, returning ... ");
return toReturn;
}
title = titles.item(0).getFirstChild().getNodeValue();
MetaSeeker ms = null;
try {
ms = new MetaSeeker(link);
} catch(Exception e) {
_log.error("[MANUAL-PARSE] Something wrong with the meta seeker returning ... ");
return toReturn;
}
//try the metadata, otherwise ask the guesser
description = (ms.getContent("description") != null && ! ms.getContent("description").isEmpty()) ? ms.getContent("description") : createDescriptionFromContent(link);
ArrayList<String> images = new ArrayList<String>();
NodeList imgs = document.getElementsByTagName("img");
int upTo = (imgs.getLength() > 15) ? 15 : imgs.getLength();
for (int i = 0; i < upTo; i++) {
String imageUrl = imgs.item(i).getAttributes().getNamedItem("src").getNodeValue();
if (imageUrl.startsWith("/"))
imageUrl = pageUrl.getProtocol()+"://"+pageUrl.getHost()+imageUrl;
images.add(imageUrl);
}
toReturn = new LinkPreview(title, description, link, host, images);
}
return toReturn;
}
/**
* generate the description parsing the content (Best Guess)
* @param link the link to check
* @return the description guessed
*/
private String createDescriptionFromContent(String link) {
StringBean sb = new StringBean();
sb.setURL(link);
sb.setLinks(false);
String description = sb.getStrings();
description = ((description.length() > 256) ? description.substring(0, 256)+"..." : description);
return description;
}
/**
* this method handles the non trusted https connections
*/
private void trustAllHTTPSConnections() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
System.out.println("Error" + e);
}
}
}

View File

@ -0,0 +1,40 @@
package org.gcube.portlets.user.shareupdates.server.metaseeker;
import java.net.URL;
/**
* Represents OpenGraph enabled meta data for a specific document
* @author Callum Jones
*/
public class MetaElement
{
private String property;
private String content;
/**
* Construct the representation of an element
* @param property The property key
* @param content The content or value of this element
*/
public MetaElement(String property, String content)
{
this.property = property;
this.content = content;
}
/**
* Fetch the content string of the element
*/
public String getContent()
{
return content;
}
/**
* Fetch the property of the element
*/
public String getProperty()
{
return property;
}
}

View File

@ -0,0 +1,211 @@
package org.gcube.portlets.user.shareupdates.server.metaseeker;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
/**
* @author Massimiliano Assante ISTI-CNR
* @version 1.0 Nov 2012
*
* This class parses the meta elements in the head of an html page and constructs a hashmap with the content attr value associated to the attr name
* e.g.
* <meta name="description" content="my description">
*
* ex. #getContent("description") returns 'my description'
*
*/
public class MetaSeeker
{
private String pageUrl;
private Hashtable<String, ArrayList<MetaElement>> metaAttributes;
private String baseType;
private boolean isImported; // determine if the object is a new incarnation or representation of a web page
private boolean hasChanged; // track if object has been changed
public final static String[] REQUIRED_META = new String[]{"title", "type", "image", "url" };
public final static Hashtable<String, String[]> BASE_TYPES = new Hashtable<String, String[]>();
static
{
BASE_TYPES.put("activity", new String[] {"activity", "sport"});
BASE_TYPES.put("business", new String[] {"bar", "company", "cafe", "hotel", "restaurant"});
BASE_TYPES.put("group", new String[] {"cause", "sports_league", "sports_team"});
BASE_TYPES.put("organization", new String[] {"band", "government", "non_profit", "school", "university"});
BASE_TYPES.put("person", new String[] {"actor", "athlete", "author", "director", "musician", "politician", "profile", "public_figure"});
BASE_TYPES.put("place", new String[] {"city", "country", "landmark", "state_province"});
BASE_TYPES.put("product", new String[] {"album", "book", "drink", "food", "game", "movie", "product", "song", "tv_show"});
BASE_TYPES.put("website", new String[] {"blog", "website", "article"});
}
/**
* Create an open graph representation for generating your own Open Graph object
*/
public MetaSeeker() {
metaAttributes = new Hashtable<String, ArrayList<MetaElement>>();
hasChanged = false;
isImported = false;
}
/**
* Fetch the metas representation from a web site
* @param url The address to the web page to fetch the meta
* @throws java.io.IOException If a network error occurs, the HTML parser will throw an IO Exception
*/
public MetaSeeker(String url) throws java.io.IOException, Exception {
this();
isImported = true;
// download the (X)HTML content, but only up to the closing head tag. We do not want to waste resources parsing irrelevant content
URL httpURL = new URL(url);
BufferedReader dis = new BufferedReader(new InputStreamReader(httpURL.openStream()));
String inputLine;
StringBuffer headContents = new StringBuffer();
// Loop through each line, looking for the closing head element
while ((inputLine = dis.readLine()) != null) {
if (inputLine.contains("</head>")) {
inputLine = inputLine.substring(0, inputLine.indexOf("</head>") + 7);
inputLine = inputLine.concat("<body></body></html>");
headContents.append(inputLine + "\r\n");
break;
}
headContents.append(inputLine + "\r\n");
}
String headContentsStr = headContents.toString();
HtmlCleaner cleaner = new HtmlCleaner();
// parse the string HTML
TagNode pageData = cleaner.clean(headContentsStr);
// open only the meta tags
TagNode[] metaData = pageData.getElementsByName("meta", true);
System.out.println("meta length " + metaData.length);
for (TagNode metaElement : metaData) {
String target = null;
System.out.println("meta " + metaElement.toString());
if (metaElement.hasAttribute("name")) {
target = "name";
setProperty(metaElement.getAttributeByName(target), metaElement.getAttributeByName("content"));
}
}
pageUrl = httpURL.toExternalForm();
}
/**
* Get the basic type of the Open graph page as per the specification
* @return Base type as defined by specification, null otherwise
*/
public String getBaseType()
{
return baseType;
}
/**
* Get a value of a given Open Graph property
* @param property The Open graph property key
* @return Returns the value of the first property defined, null otherwise
*/
public String getContent(String property)
{
if (metaAttributes.containsKey(property) && metaAttributes.get(property).size() > 0)
return metaAttributes.get(property).get(0).getContent();
else
return null;
}
/**
* Get all the defined properties of the Open Graph object
* @return An array of all currently defined properties
*/
public MetaElement[] getProperties()
{
ArrayList<MetaElement> allElements = new ArrayList<MetaElement>();
for (ArrayList<MetaElement> collection : metaAttributes.values())
allElements.addAll(collection);
return (MetaElement[]) allElements.toArray(new MetaElement[allElements.size()]);
}
/**
* Get all the defined properties of the Open Graph object
* @param property The property to focus on
* @return An array of all currently defined properties
*/
public MetaElement[] getProperties(String property)
{
if (metaAttributes.containsKey(property))
{
ArrayList target = metaAttributes.get(property);
return (MetaElement[]) target.toArray(new MetaElement[target.size()]);
}
else
return null;
}
/**
* Get the original URL the Open Graph page was obtained from
* @return The address to the Open Graph object page
*/
public String getOriginalUrl()
{
return pageUrl;
}
/**
* Set the meta property to a specific value
* @param property The meta where XXXX is the property you wish to set
* @param content The value or contents of the property to be set
*/
public void setProperty(String property, String content)
{
MetaElement element = new MetaElement(property, content);
if (!metaAttributes.containsKey(property))
metaAttributes.put(property, new ArrayList<MetaElement>());
metaAttributes.get(property).add(element);
}
/**
* Removed a defined property
* @param property The og:XXXX where XXXX is the property you wish to remove
*/
public void removeProperty(String property)
{
metaAttributes.remove(property);
}
/**
* Obtain the underlying HashTable
* @return The underlying structure as a Hashtable
*/
public Hashtable<String, ArrayList<MetaElement>> exposeTable() {
return metaAttributes;
}
/**
* Test if the Open Graph object was initially a representation of a web page
* @return True if the object is from a web page, false otherwise
*/
public boolean isFromWeb()
{
return isImported;
}
/**
* Test if the object has been modified by setters/deleters.
* This is only relevant if this object initially represented a web page
* @return True True if the object has been modified, false otherwise
*/
public boolean hasChanged()
{
return hasChanged;
}
}

View File

@ -0,0 +1,51 @@
package org.gcube.portlets.user.shareupdates.server.opengraph;
import java.net.URL;
/**
* Represents OpenGraph enabled meta data for a specific document
* @author Callum Jones
*/
public class MetaElement
{
private OpenGraphNamespace namespace; //either "og" an NS specific
private String property;
private String content;
/**
* Construct the representation of an element
* @param namespace The namespace the element belongs to
* @param property The property key
* @param content The content or value of this element
*/
public MetaElement(OpenGraphNamespace namespace, String property, String content)
{
this.namespace = namespace;
this.property = property;
this.content = content;
}
/**
* Fetch the content string of the element
*/
public String getContent()
{
return content;
}
/**
* Fetch the OpenGraph namespace
*/
public OpenGraphNamespace getNamespace()
{
return namespace;
}
/**
* Fetch the property of the element
*/
public String getProperty()
{
return property;
}
}

View File

@ -0,0 +1,378 @@
package org.gcube.portlets.user.shareupdates.server.opengraph;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A Java object representation of an Open Graph enabled webpage.
* A simplified layer over a Hastable.
*
* @author Callum Jones
*/
public class OpenGraph
{
private String pageUrl;
private ArrayList<OpenGraphNamespace> pageNamespaces;
private Hashtable<String, ArrayList<MetaElement>> metaAttributes;
private String baseType;
private boolean isImported; // determine if the object is a new incarnation or representation of a web page
private boolean hasChanged; // track if object has been changed
public final static String[] REQUIRED_META = new String[]{"title", "type", "image", "url" };
public final static Hashtable<String, String[]> BASE_TYPES = new Hashtable<String, String[]>();
static
{
BASE_TYPES.put("activity", new String[] {"activity", "sport"});
BASE_TYPES.put("business", new String[] {"bar", "company", "cafe", "hotel", "restaurant"});
BASE_TYPES.put("group", new String[] {"cause", "sports_league", "sports_team"});
BASE_TYPES.put("organization", new String[] {"band", "government", "non_profit", "school", "university"});
BASE_TYPES.put("person", new String[] {"actor", "athlete", "author", "director", "musician", "politician", "profile", "public_figure"});
BASE_TYPES.put("place", new String[] {"city", "country", "landmark", "state_province"});
BASE_TYPES.put("product", new String[] {"album", "book", "drink", "food", "game", "movie", "product", "song", "tv_show"});
BASE_TYPES.put("website", new String[] {"blog", "website", "article"});
}
/**
* Create an open graph representation for generating your own Open Graph object
*/
public OpenGraph()
{
pageNamespaces = new ArrayList<OpenGraphNamespace>();
metaAttributes = new Hashtable<String, ArrayList<MetaElement>>();
hasChanged = false;
isImported = false;
}
/**
* Fetch the open graph representation from a web site
* @param url The address to the web page to fetch Open Graph data
* @param ignoreSpecErrors Set this option to true if you don't wish to have an exception throw if the page does not conform to the basic 4 attributes
* @throws java.io.IOException If a network error occurs, the HTML parser will throw an IO Exception
* @throws java.lang.Exception A generic exception is throw if the specific page fails to conform to the basic Open Graph standard as define by the constant REQUIRED_META
*/
public OpenGraph(String url, boolean ignoreSpecErrors, URLConnection siteConnection) throws java.io.IOException, Exception {
this();
isImported = true;
// download the (X)HTML content, but only up to the closing head tag. We do not want to waste resources parsing irrelevant content
Charset charset = getConnectionCharset(siteConnection);
BufferedReader dis = new BufferedReader(new InputStreamReader(siteConnection.getInputStream(), charset));
String inputLine;
StringBuffer headContents = new StringBuffer();
// Loop through each line, looking for the closing head element
while ((inputLine = dis.readLine()) != null)
{
if (inputLine.contains("</head>"))
{
inputLine = inputLine.substring(0, inputLine.indexOf("</head>") + 7);
inputLine = inputLine.concat("<body></body></html>");
headContents.append(inputLine + "\r\n");
break;
}
headContents.append(inputLine + "\r\n");
}
String headContentsStr = headContents.toString();
HtmlCleaner cleaner = new HtmlCleaner();
// parse the string HTML
TagNode pageData = cleaner.clean(headContentsStr);
// read in the declared namespaces
boolean hasOGspec = false;
TagNode headElement = pageData.findElementByName("head", true);
if (headElement.hasAttribute("prefix"))
{
String namespaceData = headElement.getAttributeByName("prefix");
Pattern pattern = Pattern.compile("(([A-Za-z0-9_]+):\\s+(http:\\/\\/ogp.me\\/ns(\\/\\w+)*#))\\s*");
Matcher matcher = pattern.matcher(namespaceData);
while (matcher.find())
{
String prefix = matcher.group(2);
String documentURI = matcher.group(3);
pageNamespaces.add(new OpenGraphNamespace(prefix, documentURI));
if (prefix.equals("og"))
hasOGspec = true;
}
}
// some pages do not include the new OG spec
// this fixes compatibility
if (!hasOGspec)
pageNamespaces.add(new OpenGraphNamespace("og", "http:// ogp.me/ns#"));
// open only the meta tags
TagNode[] metaData = pageData.getElementsByName("meta", true);
for (TagNode metaElement : metaData)
{
for (OpenGraphNamespace namespace : pageNamespaces)
{
String target = null;
if (metaElement.hasAttribute("property"))
target = "property";
else if (metaElement.hasAttribute("name"))
target = "name";
if (target != null && metaElement.getAttributeByName(target).startsWith(namespace.getPrefix() + ":"))
{
setProperty(namespace, metaElement.getAttributeByName(target), metaElement.getAttributeByName("content"));
break;
}
}
}
/**
* Check that page conforms to Open Graph protocol
*/
if (!ignoreSpecErrors)
{
for (String req : REQUIRED_META)
{
if (!metaAttributes.containsKey(req))
throw new Exception("Does not conform to Open Graph protocol");
}
}
/**
* Has conformed, now determine basic sub type.
*/
baseType = null;
String currentType = getContent("type");
// read the original page url
URL realURL = siteConnection.getURL();
pageUrl = realURL.toExternalForm();
}
/**
* Gets the charset for specified connection.
* Content Type header is parsed to get the charset name.
*
* @param connection the connection.
* @return the Charset object for response charset name;
* if it's not found then the default charset.
*/
private static Charset getConnectionCharset(URLConnection connection)
{
String contentType = connection.getContentType();
if (contentType != null && contentType.length() > 0)
{
contentType = contentType.toLowerCase();
String charsetName = extractCharsetName(contentType);
if (charsetName != null && charsetName.length() > 0)
{
try
{
return Charset.forName(charsetName);
}
catch (Exception e) {
// specified charset is not found,
// skip it to return the default one
}
}
}
// return the default charset
return Charset.defaultCharset();
}
/**
* Extract the charset name form the content type string.
* Content type string is received from Content-Type header.
*
* @param contentType the content type string, must be not null.
* @return the found charset name or null if not found.
*/
private static String extractCharsetName(String contentType)
{
// split onto media types
final String[] mediaTypes = contentType.split(":");
if (mediaTypes.length > 0)
{
// use only the first one, and split it on parameters
final String[] params = mediaTypes[0].split(";");
// find the charset parameter and return it's value
for (String each : params)
{
each = each.trim();
if (each.startsWith("charset="))
{
// return the charset name
return each.substring(8).trim();
}
}
}
return null;
}
/**
* Get the basic type of the Open graph page as per the specification
* @return Base type as defined by specification, null otherwise
*/
public String getBaseType()
{
return baseType;
}
/**
* Get a value of a given Open Graph property
* @param property The Open graph property key
* @return Returns the value of the first property defined, null otherwise
*/
public String getContent(String property)
{
if (metaAttributes.containsKey(property) && metaAttributes.get(property).size() > 0)
return metaAttributes.get(property).get(0).getContent();
else
return null;
}
/**
* Get all the defined properties of the Open Graph object
* @return An array of all currently defined properties
*/
public MetaElement[] getProperties()
{
ArrayList<MetaElement> allElements = new ArrayList<MetaElement>();
for (ArrayList<MetaElement> collection : metaAttributes.values())
allElements.addAll(collection);
return (MetaElement[]) allElements.toArray(new MetaElement[allElements.size()]);
}
/**
* Get all the defined properties of the Open Graph object
* @param property The property to focus on
* @return An array of all currently defined properties
*/
public MetaElement[] getProperties(String property)
{
if (metaAttributes.containsKey(property))
{
ArrayList target = metaAttributes.get(property);
return (MetaElement[]) target.toArray(new MetaElement[target.size()]);
}
else
return null;
}
/**
* Get the original URL the Open Graph page was obtained from
* @return The address to the Open Graph object page
*/
public String getOriginalUrl()
{
return pageUrl;
}
/**
* Get the HTML representation of the Open Graph data.
* @return An array of meta elements as Strings
*/
public String[] toHTML()
{
// allocate the array
ArrayList<String> returnHTML = new ArrayList<String>();
int index = 0; // keep track of the index to insert into
for (ArrayList<MetaElement> elements : metaAttributes.values())
{
for (MetaElement element : elements)
returnHTML.add("<meta property=\"" + element.getNamespace() + ":" +
element.getProperty() + "\" content=\"" + element.getContent() + "\" />");
}
// return the array
return (String[]) returnHTML.toArray();
}
/**
* Get the XHTML representation of the Open Graph data.
* @return An array of meta elements as Strings
*/
public String[] toXHTML()
{
// allocate the array
ArrayList<String> returnHTML = new ArrayList<String>();
int index = 0; // keep track of the index to insert into
for (ArrayList<MetaElement> elements : metaAttributes.values())
{
for (MetaElement element : elements)
returnHTML.add("<meta name=\"" + element.getNamespace().getPrefix() + ":" +
element.getProperty() + "\" content=\"" + element.getContent() + "\" />");
}
// return the array
return (String[]) returnHTML.toArray();
}
/**
* Set the Open Graph property to a specific value
* @param namespace The OpenGraph namespace the content belongs to
* @param property The og:XXXX where XXXX is the property you wish to set
* @param content The value or contents of the property to be set
*/
public void setProperty(OpenGraphNamespace namespace, String property, String content)
{
if (!pageNamespaces.contains(namespace))
pageNamespaces.add(namespace);
property = property.replaceAll(namespace.getPrefix() + ":", "");
MetaElement element = new MetaElement(namespace, property, content);
if (!metaAttributes.containsKey(property))
metaAttributes.put(property, new ArrayList<MetaElement>());
metaAttributes.get(property).add(element);
}
/**
* Removed a defined property
* @param property The og:XXXX where XXXX is the property you wish to remove
*/
public void removeProperty(String property)
{
metaAttributes.remove(property);
}
/**
* Obtain the underlying HashTable
* @return The underlying structure as a Hashtable
*/
public Hashtable<String, ArrayList<MetaElement>> exposeTable() {
return metaAttributes;
}
/**
* Test if the Open Graph object was initially a representation of a web page
* @return True if the object is from a web page, false otherwise
*/
public boolean isFromWeb()
{
return isImported;
}
/**
* Test if the object has been modified by setters/deleters.
* This is only relevant if this object initially represented a web page
* @return True True if the object has been modified, false otherwise
*/
public boolean hasChanged()
{
return hasChanged;
}
}

View File

@ -0,0 +1,38 @@
package org.gcube.portlets.user.shareupdates.server.opengraph;
/**
* Represents an OpenGraph namespace
* @author Callum Jones
*/
public class OpenGraphNamespace
{
private String prefix;
private String schemaURI;
/**
* Construct a namespace
* @param prefix The OpenGraph assigned namespace prefix such as og or og_appname
* @param schemaURI The URL for the OpenGraph schema
*/
public OpenGraphNamespace(String prefix, String schemaURI)
{
this.prefix = prefix;
this.schemaURI = schemaURI;
}
/*
* Fetch the prefix used for the namespace
*/
public String getPrefix()
{
return prefix;
}
/*
* Fetch the address for the schema reference
*/
public String getSchemaURI()
{
return schemaURI;
}
}

View File

@ -0,0 +1,32 @@
package org.gcube.portlets.user.shareupdates.server.portlet;
import javax.portlet.GenericPortlet;
import javax.portlet.ActionRequest;
import javax.portlet.RenderRequest;
import javax.portlet.ActionResponse;
import javax.portlet.RenderResponse;
import javax.portlet.PortletException;
import java.io.IOException;
import javax.portlet.PortletRequestDispatcher;
import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper;
/**
* WfTemplatesPortlet Portlet Class
*
* @author Massimiliano Assante, ISTI-CNR - massimiliano.assante@isti.cnr.it
* @version May 2011 (0.1)
*/
public class ShareUpdatesPortlet extends GenericPortlet {
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
response.setContentType("text/html");
ScopeHelper.setContext(request);
PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/ShareUpdates_view.jsp");
dispatcher.include(request, response);
}
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
}
}

View File

@ -0,0 +1,42 @@
package org.gcube.portlets.user.shareupdates.shared;
/**
* <p>
* FieldVerifier validates that the name the user enters is valid.
* </p>
* <p>
* This class is in the <code>shared</code> packing because we use it in both
* the client code and on the server. On the client, we verify that the name is
* valid before sending an RPC request so the user doesn't have to wait for a
* network round trip to get feedback. On the server, we verify that the name is
* correct to ensure that the input is correct regardless of where the RPC
* originates.
* </p>
* <p>
* When creating a class that is used on both the client and the server, be sure
* that all code is translatable and does not use native JavaScript. Code that
* is note translatable (such as code that interacts with a database or the file
* system) cannot be compiled into client side JavaScript. Code that uses native
* JavaScript (such as Widgets) cannot be run on the server.
* </p>
*/
public class FieldVerifier {
/**
* Verifies that the specified name is valid for our service.
*
* In this example, we only require that the name is at least four
* characters. In your application, you can use more complex checks to ensure
* that usernames, passwords, email addresses, URLs, and other fields have the
* proper syntax.
*
* @param name the name to validate
* @return true if valid, false if invalid
*/
public static boolean isValidName(String name) {
if (name == null) {
return false;
}
return name.length() > 3;
}
}

View File

@ -0,0 +1,79 @@
package org.gcube.portlets.user.shareupdates.shared;
import java.io.Serializable;
import java.util.ArrayList;
@SuppressWarnings("serial")
public class LinkPreview implements Serializable {
private String title;
private String description;
private String url;
private String host;
private ArrayList<String> imageUrls;
public LinkPreview() {
super();
}
public LinkPreview(String title, String description, String url,
String host, ArrayList<String> imageUrls) {
super();
this.title = title;
this.description = description;
this.url = url;
this.host = host;
this.imageUrls = imageUrls;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
/**
*
* @return
*/
public String getTitle() {
return title;
}
/**
*
* @param title
*/
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public ArrayList<String> getImageUrls() {
return imageUrls;
}
public void setImageUrls(ArrayList<String> imageUrls) {
this.imageUrls = imageUrls;
}
@Override
public String toString() {
return "LinkPreview [title=" + title + ", description=" + description
+ ", url=" + url + ", host=" + host + ", imageUrls="
+ imageUrls + "]";
}
}

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='shareupdates'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User' />
<inherits name="net.eliasbalasis.tibcopagebus4gwt.tibcopagebus4gwt" />
<inherits name="org.jsonmaker.gwt.Gwt_jsonmaker" />
<!-- inherits GCUBE Widgets -->
<inherits name='org.gcube.portlets.user.gcubewidgets.WidgetFactory' />
<inherits
name="net.eliasbalasis.tibcopagebus4gwt.testsubscriber.TestSubscriber" />
<!-- To Comment out -->
<!-- <set-property name="user.agent" value="gecko1_8" /> -->
<!-- Other module inherits -->
<inherits name='org.gcube.portal.databook.GCubeSocialNetworking' />
<!-- Specify the app entry point class. -->
<entry-point class='org.gcube.portlets.user.shareupdates.client.ShareUpdates' />
<!-- Specify the paths for translatable code -->
<source path='client' />
<source path='shared' />
</module>

View File

@ -0,0 +1,174 @@
.buttonDiv {
text-align: right;
padding-top: 2px;
}
.member-photo {
display: block;
padding: 2px;
border: 1px solid #E6E6E6;
}
.link-previewer {
width: 600px;
padding-top: 10px;
padding-bottom: 10px;
font-family: 'lucida grande', tahoma, verdana, arial, sans-serif;
background-clip: border-box;
background-color: #FBFBFB;
background-image: none;
border-color: #D7D7D7;
}
.hide-description {
margin-top: 5px;
}
.hide-description span label{
padding-left: 5px;
}
.linkpreview-bgcolor {
background-color: #FBFBFB;
}
.link-title {
font-size: 12px;
font-weight: bold;
line-height: 15px;
width: 465px;
}
.link-url {
color: #666;
font-size: 10px;
}
.link-desc {
padding-top: 5px;
color: #333;
font-size: 10px;
width: 465px;
}
.image-loader {
background: #FFF url(images/avatarLoader.gif) no-repeat;
}
.su-closeImage {
background: url(images/close.png) 0px 0px no-repeat;
height: 15px;
width: 15px;
}
.su-closeImage:hover {
background: url(images/close.png) 0px -16px no-repeat;
cursor: pointer;
cursor: hand;
}
.su-closeImage:active {
background: url(images/close.png) 0px -32px no-repeat;
}
.small-text {
font-family: 'lucida grande', tahoma, verdana, arial, sans-serif;
font-size: 9px;
}
.small-text-arrow {
font-family: 'lucida grande', tahoma, verdana, arial, sans-serif;
font-size: 9px;
padding-left: 5px;
padding-right: 5px;
}
.small-text-arrow:hover {
color: blue;
cursor: pointer;
cursor: hand;
}
a.link,a.link:active,a.link:visited {
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 12px;
cursor: pointer;
cursor: hand;
text-decoration: none;
color: #3B5998;
}
a.link:hover {
opacity: 0.8;
text-decoration: underline;
}
.shareContainer {
width: 600px;
background-clip: border-box;
background-image: none;
background-origin: padding-box;
padding-bottom: 3px;
}
.shareContainer-in {
padding-left: 5px;
}
.post-message {
height: 54px;
color: #999;
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 13px;
padding: 4px 2px;
width: 99%;
border-color: #999;
border-width: 1px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
letter-spacing: normal;
}
.dark-color {
color: #333;
background-color: #FFF;
transition: background .25s ease-in-out;
-moz-transition: background .25s ease-in-out;
-webkit-transition: background .25s ease-in-out;
}
.toolsContainer {
padding-top: 3px;
width: 600px;
background-image: none;
border-top-color: #DADADA;
border-top-style: solid;
border-top-width: 1px;
}
.wizardListbox {
height: 19px;
width: 110px;
background: #F2F2F2 url(images/white-grad.png) repeat-x scroll left top;
border-color: #BBB;
color: #464646;
font-size: 10px;
border-width: 1px;
border-style: solid;
cursor: pointer;
cursor: hand;
padding-bottom: 3px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.error {
color: #FFF;
background-color: pink;
transition: background .45s ease-in-out;
-moz-transition: background .45s ease-in-out;
-webkit-transition: background .45s ease-in-out;
}

View File

@ -0,0 +1,23 @@
<!doctype html>
<!-- The DOCTYPE declaration above will set the -->
<!-- browser's rendering engine into -->
<!-- "Standards Mode". Replacing this declaration -->
<!-- with a "Quirks Mode" doctype may lead to some -->
<!-- differences in layout. -->
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!-- -->
<!-- Consider inlining CSS to reduce the number of requested files -->
<!-- -->
<link type="text/css" rel="stylesheet" href="ShareUpdates.css">
<script type="text/javascript" language="javascript" src="shareupdates/shareupdates.nocache.js"></script>
</head>
<body>
<div id="shareUpdateDiv"></div>
</body>
</html>

View File

@ -0,0 +1,19 @@
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%-- Uncomment below lines to add portlet taglibs to jsp
<%@ page import="javax.portlet.*"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<portlet:defineObjects />
--%>
<script type="text/javascript">
if(window.parent.PageBus) {
window.PageBus = window.parent.PageBus;
}
</script>
<script type="text/javascript" language="javascript"
src='<%=request.getContextPath()%>/shareupdates/shareupdates.nocache.js'></script>
<div id="shareUpdateDiv"></div>

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<!DOCTYPE display PUBLIC "-//Liferay//DTD Display 6.0.0//EN" "http://www.liferay.com/dtd/liferay-display_6_0_0.dtd">
<display>
<category name="gCube Social Apps">
<portlet id="ShareUpdates" />
</category>
</display>

View File

@ -0,0 +1,9 @@
name=ShareUpdates
module-group-id=liferay
module-incremental-version=1
tags=
short-description=
change-log=
page-url=http://www.liferay.com
author=Liferay, Inc.
licenses=LGPL

View File

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 5.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_0_0.dtd">
<liferay-portlet-app>
<portlet>
<portlet-name>ShareUpdates</portlet-name>
<layout-cacheable>false</layout-cacheable>
<instanceable>false</instanceable>
<ajaxable>false</ajaxable>
<header-portlet-css>/ShareUpdates.css</header-portlet-css>
<header-portlet-javascript>/js/pagebus.js</header-portlet-javascript>
</portlet>
<role-mapper>
<role-name>administrator</role-name>
<role-link>Administrator</role-link>
</role-mapper>
<role-mapper>
<role-name>guest</role-name>
<role-link>Guest</role-link>
</role-mapper>
<role-mapper>
<role-name>power-user</role-name>
<role-link>Power User</role-link>
</role-mapper>
<role-mapper>
<role-name>user</role-name>
<role-link>User</role-link>
</role-mapper>
</liferay-portlet-app>

View File

@ -0,0 +1,30 @@
<?xml version="1.0"?>
<portlet-app
version="2.0"
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
>
<portlet>
<portlet-name>ShareUpdates</portlet-name>
<display-name>ShareUpdates</display-name>
<portlet-class>org.gcube.portlets.user.shareupdates.server.portlet.ShareUpdatesPortlet</portlet-class>
<init-param>
<name>view-jsp</name>
<value>/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<portlet-info>
<title>Share updates</title>
<short-title>Share</short-title>
<keywords>Share Updates</keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
</portlet>
</portlet-app>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee">
<!-- Servlets -->
<servlet>
<servlet-name>shareupdateServlet</servlet-name>
<servlet-class>org.gcube.portlets.user.shareupdates.server.ShareUpdateServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>shareupdateServlet</servlet-name>
<url-pattern>/shareupdates/shareupdateServlet</url-pattern>
</servlet-mapping>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>ShareUpdates.html</welcome-file>
</welcome-file-list>
</web-app>

Binary file not shown.

After

Width:  |  Height:  |  Size: 997 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

View File

@ -0,0 +1,182 @@
/**
* Copyright (c) 2006-2007, TIBCO Software Inc.
* Use, modification, and distribution subject to terms of license.
*
* TIBCO(R) PageBus 1.1.0
*/
if(typeof window.PageBus == 'undefined') {
PageBus = {
version: "1.1.0",
S: {c:{},s:[]},
X: 0,
P: 0,
U: [],
H: "undefined"
};
PageBus.subscribe = function(name, scope, callback, subscriberData)
{
if(name == null)
this._badName();
if(scope == null)
scope = window;
var path = name.split(".");
var sub = { f: callback, d: subscriberData, i: this.X++, p: path, w: scope };
for(var i = 0; i < path.length; i++) {
if((path[i].indexOf("*") != -1) && (path[i] != "*") && (path[i] != "**"))
this._badName();
}
this._subscribe(this.S, path, 0, sub);
return sub;
}
PageBus.publish = function (name, message)
{
if((name == null) || (name.indexOf("*") != -1))
this._badName();
var path = name.split(".");
if(this.P > 100)
this._throw("StackOverflow");
try {
this.P++;
this._publish(this.S, path, 0, name, message);
}
catch(err) {
this.P--;
throw err;
}
try {
this.P--;
if((this.U.length > 0) && (this.P == 0)) {
for(var i = 0; i < this.U.length; i++)
this.unsubscribe(this.U[i]);
this.U = [];
}
}
catch(err) {
// All unsubscribe exceptions should already have
// been handled when unsubscribe was called in the
// publish callback. This is a repeat appearance
// of this exception. Discard it.
}
}
PageBus.unsubscribe = function(sub)
{
this._unsubscribe(this.S, sub.p, 0, sub.i);
}
/*
* @private @jsxobf-clobber
*/
PageBus._throw = function(n)
{
throw new Error("PageBus." + n);
}
/*
* @private @jsxobf-clobber
*/
PageBus._badName = function(n)
{
this._throw("BadName");
}
/*
* @private @jsxobf-clobber
*/
PageBus._subscribe = function(tree, path, index, sub)
{
var tok = path[index];
if(tok == "")
this._badName();
if(index == path.length)
tree.s.push(sub);
else {
if(typeof tree.c == this.H)
tree.c = {};
if(typeof tree.c[tok] == this.H) {
try {
tree.c[tok] = { c: {}, s: [] };
this._subscribe(tree.c[tok], path, index + 1, sub);
}
catch(err) {
delete tree.c[tok];
throw err;
}
}
else
this._subscribe( tree.c[tok], path, index + 1, sub );
}
}
/*
* @private @jsxobf-clobber
*/
PageBus._publish = function(tree, path, index, name, msg) {
if(path[index] == "")
this._badName();
if(typeof tree != this.H) {
if(index < path.length) {
this._publish(tree.c[path[index]], path, index + 1, name, msg);
this._publish(tree.c["*"], path, index + 1, name, msg);
this._call(tree.c["**"], name, msg);
}
else
this._call(tree, name, msg);
}
}
/*
* @private @jsxobf-clobber
*/
PageBus._call = function(node, name, msg) {
if(typeof node != this.H) {
var callbacks = node.s;
var max = callbacks.length;
for(var i = 0; i < max; i++)
if(callbacks[i].f != null)
callbacks[i].f.apply(callbacks[i].w, [name, msg, callbacks[i].d]);
}
}
/*
* @jsxobf-clobber
*/
PageBus._unsubscribe = function(tree, path, index, sid) {
if(typeof tree != this.H) {
if(index < path.length) {
var childNode = tree.c[path[index]];
this._unsubscribe(childNode, path, index + 1, sid);
if(childNode.s.length == 0) {
for(var x in childNode.c) // not empty. We're done.
return;
delete tree.c[path[index]]; // if we got here, c is empty
}
return;
}
else {
var callbacks = tree.s;
var max = callbacks.length;
for(var i = 0; i < max; i++) {
if(sid == callbacks[i].i) {
if(this.P > 0) {
if(callbacks[i].f == null)
this._throw("BadParameter");
callbacks[i].f = null;
this.U.push(callbacks[i]);
}
else
callbacks.splice(i, 1);
return;
}
}
// Not found. Fall through
}
}
this._throw("BadParameter");
}
}

View File

@ -0,0 +1,39 @@
package org.gcube.portlets.user.shareupdates.client;
import com.google.gwt.junit.client.GWTTestCase;
/**
* GWT JUnit <b>integration</b> tests must extend GWTTestCase.
* Using <code>"GwtTest*"</code> naming pattern exclude them from running with
* surefire during the test phase.
*
* If you run the tests using the Maven command line, you will have to
* navigate with your browser to a specific url given by Maven.
* See http://mojo.codehaus.org/gwt-maven-plugin/user-guide/testing.html
* for details.
*/
public class GwtTestShareUpdates extends GWTTestCase {
/**
* Must refer to a valid module that sources this class.
*/
public String getModuleName() {
return "org.gcube.portlets.user.shareupdates.ShareUpdatesJUnit";
}
/**
* Tests the FieldVerifier.
*/
public void testFieldVerifier() {
}
/**
* This test will send a request to the server using the greetServer method in
* GreetingService and verify the response.
*/
public void testGreetingService() {
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module>
<!-- Inherit our applications main module. -->
<inherits name='org.gcube.portlets.user.shareupdates.ShareUpdates' />
</module>