Author: ndkhoiits
Date: 2011-01-26 22:56:42 -0500 (Wed, 26 Jan 2011)
New Revision: 5821
Added:
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInContainerConfigLoader.java
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInGuiceServletContextListener.java
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInJsonContainerConfig.java
portal/trunk/gadgets/server/src/main/webapp/containers/
portal/trunk/gadgets/server/src/main/webapp/containers/default/
portal/trunk/gadgets/server/src/main/webapp/containers/default/container.js
Removed:
portal/trunk/gadgets/core/src/main/java/containers/default/container.js
portal/trunk/gadgets/server/src/main/webapp/WEB-INF/classes/
portal/trunk/gadgets/server/src/main/webapp/containers/default/
portal/trunk/gadgets/server/src/main/webapp/containers/default/container.js
Modified:
portal/trunk/component/portal/src/main/resources/binding.xml
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestJIBXXmlMapping.java
portal/trunk/component/resources/pom.xml
portal/trunk/component/resources/src/main/java/org/exoplatform/services/resources/impl/BaseResourceBundleService.java
portal/trunk/component/resources/src/test/java/org/exoplatform/services/resources/test/TestResourceBundleService.java
portal/trunk/examples/portal/war/src/main/webapp/WEB-INF/web.xml
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ExoContainerConfig.java
portal/trunk/gadgets/server/src/main/webapp/WEB-INF/web.xml
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_en.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_vi.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/web.xml
portal/trunk/web/portal/src/main/webapp/groovy/portal/webui/application/UIGadget.gtmpl
portal/trunk/web/portal/src/main/webapp/groovy/portal/webui/portal/UILanguageSelector.gtmpl
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/UIFormInputSet.java
portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component/UIAddGadgetForm.java
portal/trunk/webui/framework/src/main/java/org/exoplatform/webui/config/Param.java
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalSessionListener.java
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIGadget.java
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIPortletForm.java
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/PageNavigationUtils.java
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UINavigationNodeSelector.java
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/portal/UILanguageSelector.java
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/portal/UIPortal.java
Log:
GTNPORTAL-1745 Merge the commit branch of sprint 46 back to trunk
Modified: portal/trunk/component/portal/src/main/resources/binding.xml
===================================================================
--- portal/trunk/component/portal/src/main/resources/binding.xml 2011-01-26 11:48:32 UTC
(rev 5820)
+++ portal/trunk/component/portal/src/main/resources/binding.xml 2011-01-27 03:56:42 UTC
(rev 5821)
@@ -117,8 +117,8 @@
</mapping>
<mapping name="node-navigation"
class="org.exoplatform.portal.config.model.PageNavigation">
- <structure name="owner-type" usage="optional"/>
- <structure name="owner-id" usage="optional"/>
+ <value name="owner-type" field="ownerType"
usage="optional"/>
+ <value name="owner-id" field="ownerId"
usage="optional"/>
<value name="priority" field="priority"
usage="optional"/>
<collection name="page-nodes" field="pageNodes"
usage="optional"
item-type="org.exoplatform.portal.config.model.PageNode"/>
Modified:
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestJIBXXmlMapping.java
===================================================================
---
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestJIBXXmlMapping.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestJIBXXmlMapping.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -85,6 +85,8 @@
PageNavigation pageNavigation = (PageNavigation)obj;
assertEquals("portal::classic::homepage",
pageNavigation.getNode("home").getPageReference());
+ assertEquals("portal", pageNavigation.getOwnerType());
+ assertEquals("classic", pageNavigation.getOwnerId());
IMarshallingContext mctx = bfact.createMarshallingContext();
mctx.setIndent(2);
Modified: portal/trunk/component/resources/pom.xml
===================================================================
--- portal/trunk/component/resources/pom.xml 2011-01-26 11:48:32 UTC (rev 5820)
+++ portal/trunk/component/resources/pom.xml 2011-01-27 03:56:42 UTC (rev 5821)
@@ -49,6 +49,10 @@
</dependency>
<dependency>
<groupId>org.exoplatform.portal</groupId>
+ <artifactId>exo.portal.component.common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.exoplatform.portal</groupId>
<artifactId>exo.portal.component.test.core</artifactId>
<scope>test</scope>
</dependency>
Modified:
portal/trunk/component/resources/src/main/java/org/exoplatform/services/resources/impl/BaseResourceBundleService.java
===================================================================
---
portal/trunk/component/resources/src/main/java/org/exoplatform/services/resources/impl/BaseResourceBundleService.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/component/resources/src/main/java/org/exoplatform/services/resources/impl/BaseResourceBundleService.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -19,6 +19,9 @@
package org.exoplatform.services.resources.impl;
+import org.exoplatform.commons.cache.future.FutureCache;
+import org.exoplatform.commons.cache.future.FutureExoCache;
+import org.exoplatform.commons.cache.future.Loader;
import org.exoplatform.commons.utils.IOUtil;
import org.exoplatform.commons.utils.MapResourceBundle;
import org.exoplatform.commons.utils.PageList;
@@ -64,6 +67,19 @@
protected ExoCache<String, ResourceBundle> cache_;
+ private volatile FutureCache<String, ResourceBundle, ResourceBundleContext>
futureCache_;
+
+ private final Loader<String, ResourceBundle, ResourceBundleContext> loader_ =
new Loader<String, ResourceBundle, ResourceBundleContext>()
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public ResourceBundle retrieve(ResourceBundleContext context, String key) throws
Exception
+ {
+ return context.get(key);
+ }
+ };
+
private volatile List<String> initResources_;
@SuppressWarnings("unchecked")
@@ -300,7 +316,7 @@
candidateFiles.add(baseName + "_" + language + "_" + country
+ ".properties");
}
- if (language != null && language.length() > 0 )
+ if (language != null && language.length() > 0)
{
candidateFiles.add(baseName + "_" + language +
".properties");
}
@@ -395,56 +411,35 @@
boolean isClasspathResource = isClasspathResource(name);
boolean isCacheable = !isClasspathResource || !PropertyManager.isDevelopping();
- if (isCacheable)
+ if (isCacheable && isClasspathResource)
{
- if (isClasspathResource)
- {
- // Avoid naming collision
- id += "_" + cl.getClass() + "_" + cl.hashCode();
- }
- try
- {
- ResourceBundle rb = cache_.get(id);
- if (rb != null)
- {
- return rb;
- }
- }
- catch (Exception ex)
- {
- }
+ // Avoid naming collision
+ id += "_" + cl.getClass() + "_" +
System.identityHashCode(cl);
}
// Case 1: ResourceBundle of portlets, standard java API is used
if (isClasspathResource)
{
- ResourceBundle res = ResourceBundleLoader.load(name, locale, cl);
- //Cache classpath resource bundle while running portal in non-dev mode
+ // Cache classpath resource bundle while running portal in non-dev mode
if (isCacheable)
- cache_.put(id, res);
- return res;
+ {
+ ResourceBundleLoaderContext ctx = new ResourceBundleLoaderContext(name,
locale, cl);
+ ResourceBundle result = getFutureCache().get(ctx, id);
+ if (ctx.e != null)
+ {
+ // Throw the RuntimeException if it occurs to remain compatible with the
old behavior
+ throw ctx.e;
+ }
+ return result;
+ }
+ else
+ {
+ return ResourceBundleLoader.load(name, locale, cl);
+ }
}
// Case 2: ResourceBundle of portal
- try
- {
- ResourceBundle res = null;
- String rootId = name + "_" +
localeService_.getDefaultLocaleConfig().getLanguage();
- ResourceBundle parent = getResourceBundleFromDb(rootId, null, locale);
- if (parent != null)
- {
- res = getResourceBundleFromDb(id, parent, locale);
- if (res == null)
- res = parent;
- cache_.put(id, res);
- return res;
- }
- }
- catch (Exception ex)
- {
- log_.error("Error: " + id, ex);
- }
- return null;
+ return getFutureCache().get(new GetResourceBundleFromDbContext(name, locale), id);
}
public ResourceBundle getResourceBundle(String[] name, Locale locale, ClassLoader cl)
@@ -458,34 +453,165 @@
idBuf.append(n).append("_");
idBuf.append(locale);
String id = idBuf.toString();
- try
+ return getFutureCache().get(new GetResourceBundleContext(name, locale, cl), id);
+ }
+
+ protected FutureCache<String, ResourceBundle, ResourceBundleContext>
getFutureCache()
+ {
+ if (futureCache_ == null)
{
- ResourceBundle res = cache_.get(id);
- if (res != null)
- return res;
- MapResourceBundle outputBundled = new MapResourceBundle(locale);
- for (int i = 0; i < name.length; i++)
+ synchronized(this)
{
- ResourceBundle temp = getResourceBundle(name[i], locale, cl);
- if (temp != null)
+ if (futureCache_ == null)
{
- outputBundled.merge(temp);
- continue;
+ futureCache_ = new FutureExoCache<String, ResourceBundle,
ResourceBundleContext>(loader_, cache_);
}
- log_.warn("Cannot load and merge the bundle: " + name[i]);
}
- outputBundled.resolveDependencies();
- cache_.put(id, outputBundled);
- return outputBundled;
}
- catch (Exception ex)
+ return futureCache_;
+ }
+
+ abstract protected ResourceBundle getResourceBundleFromDb(String id, ResourceBundle
parent, Locale locale)
+ throws Exception;
+
+ /**
+ * Generic class defining a context needed to get a ResourceBundle
+ */
+ private static abstract class ResourceBundleContext
+ {
+ /**
+ * Get the resource bundle corresponding to the context
+ */
+ abstract ResourceBundle get(String id);
+ }
+
+ /**
+ * The class defining the context required to load a ResourceBundle thanks to the
method
+ * <code>ResourceBundleLoader.load(String name, Locale locale, ClassLoader
cl)</code>
+ */
+ private static class ResourceBundleLoaderContext extends ResourceBundleContext
+ {
+ private final String name;
+
+ private final Locale locale;
+
+ private final ClassLoader cl;
+
+ private RuntimeException e;
+
+ public ResourceBundleLoaderContext(String name, Locale locale, ClassLoader cl)
{
- log_.error("Cannot load and merge the bundle: " + id, ex);
+ this.name = name;
+ this.locale = locale;
+ this.cl = cl;
}
- return null;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ ResourceBundle get(String id)
+ {
+ try
+ {
+ return ResourceBundleLoader.load(name, locale, cl);
+ }
+ catch (RuntimeException e)
+ {
+ this.e = e;
+ }
+ return null;
+ }
}
- abstract protected ResourceBundle getResourceBundleFromDb(String id, ResourceBundle
parent, Locale locale)
- throws Exception;
+ /**
+ * The class defining the context required to load a ResourceBundle thanks to the
method
+ * <code>getResourceBundleFromDb(String id, ResourceBundle parent, Locale
locale)</code>
+ */
+ private class GetResourceBundleFromDbContext extends ResourceBundleContext
+ {
+ private final String name;
-}
+ private final Locale locale;
+
+ public GetResourceBundleFromDbContext(String name, Locale locale)
+ {
+ this.name = name;
+ this.locale = locale;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ ResourceBundle get(String id)
+ {
+ ResourceBundle res = null;
+ try
+ {
+ String rootId = name + "_" +
localeService_.getDefaultLocaleConfig().getLanguage();
+ ResourceBundle parent = getResourceBundleFromDb(rootId, null, locale);
+ if (parent != null)
+ {
+ res = getResourceBundleFromDb(id, parent, locale);
+ if (res == null)
+ res = parent;
+ }
+ }
+ catch (Exception ex)
+ {
+ log_.error("Error: " + id, ex);
+ }
+ return res;
+ }
+ }
+
+ /**
+ * The class defining the context required to load a ResourceBundle thanks to the
method
+ * <code>getResourceBundle(String[] name, Locale locale, ClassLoader
cl)</code>
+ */
+ private class GetResourceBundleContext extends ResourceBundleContext
+ {
+ private final String[] name;
+
+ private final Locale locale;
+
+ private final ClassLoader cl;
+
+ public GetResourceBundleContext(String[] name, Locale locale, ClassLoader cl)
+ {
+ this.name = name;
+ this.locale = locale;
+ this.cl = cl;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ ResourceBundle get(String id)
+ {
+ MapResourceBundle outputBundled = null;
+ try
+ {
+ outputBundled = new MapResourceBundle(locale);
+ for (int i = 0; i < name.length; i++)
+ {
+ ResourceBundle temp = getResourceBundle(name[i], locale, cl);
+ if (temp != null)
+ {
+ outputBundled.merge(temp);
+ continue;
+ }
+ log_.warn("Cannot load and merge the bundle: " + name[i]);
+ }
+ outputBundled.resolveDependencies();
+ }
+ catch (Exception ex)
+ {
+ log_.error("Cannot load and merge the bundle: " + id, ex);
+ }
+ return outputBundled;
+ }
+ }
+}
\ No newline at end of file
Modified:
portal/trunk/component/resources/src/test/java/org/exoplatform/services/resources/test/TestResourceBundleService.java
===================================================================
---
portal/trunk/component/resources/src/test/java/org/exoplatform/services/resources/test/TestResourceBundleService.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/component/resources/src/test/java/org/exoplatform/services/resources/test/TestResourceBundleService.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -211,5 +211,11 @@
{
return "MyClassLoader";
}
+
+ @Override
+ public int hashCode()
+ {
+ return 0;
+ }
}
}
Modified: portal/trunk/examples/portal/war/src/main/webapp/WEB-INF/web.xml
===================================================================
--- portal/trunk/examples/portal/war/src/main/webapp/WEB-INF/web.xml 2011-01-26 11:48:32
UTC (rev 5820)
+++ portal/trunk/examples/portal/war/src/main/webapp/WEB-INF/web.xml 2011-01-27 03:56:42
UTC (rev 5821)
@@ -141,9 +141,6 @@
<listener-class>org.exoplatform.web.GenericHttpListener</listener-class>
</listener>
<listener>
- <listener-class>org.exoplatform.portal.application.PortalSessionListener</listener-class>
- </listener>
- <listener>
<listener-class>org.exoplatform.services.security.web.JAASConversationStateListener</listener-class>
</listener>
<!-- ================================================================== -->
Deleted: portal/trunk/gadgets/core/src/main/java/containers/default/container.js
===================================================================
--- portal/trunk/gadgets/core/src/main/java/containers/default/container.js 2011-01-26
11:48:32 UTC (rev 5820)
+++ portal/trunk/gadgets/core/src/main/java/containers/default/container.js 2011-01-27
03:56:42 UTC (rev 5821)
@@ -1,180 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- *
http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// Default container configuration. To change the configuration, you have two options:
-//
-// A. If you run the Java server: Create your own "myContainer.js" file and
-// modify the value in web.xml.
-//
-// B. If you run the PHP server: Create a myContainer.js, copy the contents of
container.js to it,
-// change
-// {"gadgets.container" : ["default"],
-// to
-// {"gadgets.container" : ["myContainer"],
-// And make your changes that you need to myContainer.js.
-// Just make sure on the iframe URL you specify &container=myContainer
-// for it to use that config.
-//
-// All configurations will automatically inherit values from this
-// config, so you only need to provide configuration for items
-// that you require explicit special casing for.
-//
-// Please namespace your attributes using the same conventions
-// as you would for javascript objects, e.g. gadgets.features
-// rather than "features".
-
-// NOTE: Please _don't_ leave trailing commas because the php json parser
-// errors out on this.
-
-// Container must be an array; this allows multiple containers
-// to share configuration.
-{"gadgets.container" : ["default"],
-
-// Set of regular expressions to validate the parent parameter. This is
-// necessary to support situations where you want a single container to support
-// multiple possible host names (such as for localized domains, such as
-// <
language>.example.org. If left as null, the parent parameter will be
-// ignored; otherwise, any requests that do not include a parent
-// value matching this set will return a 404 error.
-"gadgets.parent" : null,
-
-// Should all gadgets be forced on to a locked domain?
-"gadgets.lockedDomainRequired" : false,
-
-// DNS domain on which gadgets should render.
-"gadgets.lockedDomainSuffix" : "-a.example.com:8080",
-
-// Various urls generated throughout the code base.
-// iframeBaseUri will automatically have the host inserted
-// if locked domain is enabled and the implementation supports it.
-// query parameters will be added.
-"gadgets.iframeBaseUri" : "/eXoGadgetServer/gadgets/ifr",
-
-// jsUriTemplate will have %host% and %js% substituted.
-// No locked domain special cases, but jsUriTemplate must
-// never conflict with a lockedDomainSuffix.
-"gadgets.jsUriTemplate" :
"http://%host%/eXoGadgetServer/gadgets/js/%js%",
-
-// Callback URL. Scheme relative URL for easy switch between https/http.
-"gadgets.oauthGadgetCallbackTemplate" :
"//%host%/eXoGadgetServer/gadgets/oauthcallback",
-
-// Use an insecure security token by default
-"gadgets.securityTokenType" : "secure",
-"gadgets.securityTokenKeyFile" : "key.txt",
-
-"gadgets.signingKeyFile" : "oauthkey.pem",
-"gadgets.signingKeyName" : "mytestkey",
-
-"gadgets.signedFetchDomain" : "eXo",
-// Config param to load Opensocial data for social
-// preloads in data pipelining. %host% will be
-// substituted with the current host.
-"gadgets.osDataUri" : "http://%host%/social/rpc",
-
-// Uncomment these to switch to a secure version
-//
-//"gadgets.securityTokenType" : "secure",
-//"gadgets.securityTokenKeyFile" : "/path/to/key/file.txt",
-
-"gadgets.content-rewrite" : {
- "include-urls": ".*",
- "exclude-urls": "",
- "include-tags": ["link", "script", "embed",
"img", "style"],
- "expires": "86400",
- "proxy-url": "/eXoGadgetServer/gadgets/proxy?url=",
- "concat-url": "/eXoGadgetServer/gadgets/concat?"
-},
-
-// This config data will be passed down to javascript. Please
-// configure your object using the feature name rather than
-// the javascript name.
-
-// Only configuration for required features will be used.
-// See individual feature.xml files for configuration details.
-"gadgets.features" : {
- "core.io" : {
- // Note: /proxy is an open proxy. Be careful how you expose this!
- "proxyUrl" :
"http://%host%/eXoGadgetServer/gadgets/proxy?refresh=%refresh%&url=%url%",
- "jsonProxyUrl" :
"http://%host%/eXoGadgetServer/gadgets/makeRequest"
- },
- "views" : {
- "home" : {
- "isOnlyVisible" : false,
- "urlTemplate" :
"http://%host%/eXoGadgetServer/gadgets/home?{var}",
- "aliases": ["DASHBOARD", "default"]
- },
- "canvas" : {
- "isOnlyVisible" : true,
- "urlTemplate" :
"http://%host%/eXoGadgetServer/gadgets/canvas?{var}",
- "aliases" : ["FULL_PAGE"]
- }
- },
- "rpc" : {
- // Path to the relay file. Automatically appended to the parent
- /// parameter if it passes input validation and is not null.
- // This should never be on the same host in a production environment!
- // Only use this for TESTING!
- "parentRelayUrl" :
"/eXoGadgetServer/gadgets/files/container/rpc_relay.html",
-
- // If true, this will use the legacy ifpc wire format when making rpc
- // requests.
- "useLegacyProtocol" : false
- },
- // Skin defaults
- "skins" : {
- "properties" : {
- "BG_COLOR": "",
- "BG_IMAGE": "",
- "BG_POSITION": "",
- "BG_REPEAT": "",
- "FONT_COLOR": "",
- "ANCHOR_COLOR": ""
- }
- },
- "opensocial-0.8" : {
- // Path to fetch opensocial data from
- // Must be on the same domain as the gadget rendering server
- "path" : "http://%host%/social",
- "domain" : "shindig",
- "enableCaja" : false,
- "supportedFields" : {
- "person" : ["id", {"name" : ["familyName",
"givenName", "unstructured"]}, "thumbnailUrl",
"profileUrl"],
- "activity" : ["id", "title"]
- }
- },
- "osapi.services" : {
- // Specifying a binding to "container.listMethods" instructs osapi to
dynamicaly introspect the services
- // provided by the container and delay the gadget onLoad handler until that
introspection is
- // complete.
- // Alternatively a container can directly configure services here rather than having
them
- // introspected. Simply list out the available servies and omit
"container.listMethods" to
- // avoid the initialization delay caused by gadgets.rpc
- // E.g. "gadgets.rpc" : ["activities.requestCreate",
"messages.requestSend", "requestShareApp",
"requestPermission"]
- "gadgets.rpc" : ["container.listMethods"]
- },
-// "osapi" : {
-// // The endpoints to query for available JSONRPC/REST services
-// "endPoints" : [ "http://%host%/social/rpc",
"http://%host%/gadgets/api/rpc" ]
-// },
- "osml": {
- // OSML library resource. Can be set to null or the empty string to disable OSML
- // for a container.
- "library": ""
- }
-}}
Modified:
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ExoContainerConfig.java
===================================================================
---
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ExoContainerConfig.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ExoContainerConfig.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -27,7 +27,6 @@
import org.apache.shindig.auth.BlobCrypterSecurityTokenDecoder;
import org.apache.shindig.config.ContainerConfigException;
-import org.apache.shindig.config.JsonContainerConfig;
import org.apache.shindig.expressions.Expressions;
import org.exoplatform.commons.utils.Safe;
import org.exoplatform.container.monitor.jvm.J2EEServerInfo;
@@ -62,7 +61,7 @@
@Singleton
public class
- ExoContainerConfig extends JsonContainerConfig
+ ExoContainerConfig extends GateInJsonContainerConfig
{
/** . */
Copied:
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInContainerConfigLoader.java
(from rev 5820,
portal/branches/branch-GTNPORTAL-1745/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInContainerConfigLoader.java)
===================================================================
---
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInContainerConfigLoader.java
(rev 0)
+++
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInContainerConfigLoader.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -0,0 +1,18 @@
+package org.exoplatform.portal.gadget.core;
+
+import javax.servlet.ServletContext;
+import java.io.IOException;
+
+/**
+ * A generic loader, used to load gadget server configuration files. We abuse the
ThreadLocal here, as there is no way
+ * to associate Guice components with Kernel 's configuration loader component
(ConfigurationManager)
+ *
+ * User: Minh Hoang TO - hoang281283(a)gmail.com
+ * Date: 1/12/11
+ * Time: 3:31 PM
+ */
+public abstract class GateInContainerConfigLoader {
+
+ public abstract String loadContentAsString(String path, String encoding) throws
IOException;
+
+}
Copied:
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInGuiceServletContextListener.java
(from rev 5820,
portal/branches/branch-GTNPORTAL-1745/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInGuiceServletContextListener.java)
===================================================================
---
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInGuiceServletContextListener.java
(rev 0)
+++
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInGuiceServletContextListener.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -0,0 +1,77 @@
+package org.exoplatform.portal.gadget.core;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.shindig.common.servlet.GuiceServletContextListener;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ *
+ * Extending the GuiceServletContextListener to setup a
ThreadLocal<GateInContainerConfigLoader> variable wrapping
+ * the ServletContext. That makes the ServletContext accessible within the scope of
thread executing the method
+ * contextInitialized
+ *
+ *
+ * User: Minh Hoang TO - hoang281283(a)gmail.com
+ * Date: 1/12/11
+ * Time: 3:50 PM
+ */
+public class GateInGuiceServletContextListener extends GuiceServletContextListener {
+
+ private static ThreadLocal<GateInContainerConfigLoader> currentLoader = new
ThreadLocal<GateInContainerConfigLoader>();
+
+ @Override
+ public void contextInitialized(ServletContextEvent event) {
+
+ final ServletContext scontext = event.getServletContext();
+
+ GateInContainerConfigLoader loader = new GateInContainerConfigLoader() {
+ @Override
+ public String loadContentAsString(String path, String encoding) throws
IOException{
+
+ //To make sure that the path begins with a slash, as required in the javadoc of
method
+ // getResourceAsStream in ServletContext
+ //The leading slash is required on certain application servers such as JBoss,
WebSphere
+ if('/' != path.charAt(0))
+ {
+ path = '/' + path;
+ }
+
+ InputStream is = scontext.getResourceAsStream(path);
+
+ if(is == null)
+ {
+ throw new NullPointerException("There is no file specified by path :
" + path);
+ }
+ return IOUtils.toString(is, encoding);
+ }
+ };
+
+ //Setup the threadlocal loader
+ currentLoader.set(loader);
+
+ try
+ {
+ //Setup the Guice objects, the threadlocal loader is accessible for the moment
+ super.contextInitialized(event);
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ //Reset the threadlocal loader to null
+ currentLoader.set(null);
+ }
+
+ }
+
+ public static GateInContainerConfigLoader getCurrentLoader()
+ {
+ return currentLoader.get();
+ }
+}
Copied:
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInJsonContainerConfig.java
(from rev 5820,
portal/branches/branch-GTNPORTAL-1745/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInJsonContainerConfig.java)
===================================================================
---
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInJsonContainerConfig.java
(rev 0)
+++
portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/GateInJsonContainerConfig.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -0,0 +1,404 @@
+/**
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+
+package org.exoplatform.portal.gadget.core;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.shindig.common.JsonSerializer;
+import org.apache.shindig.common.util.ResourceLoader;
+import org.apache.shindig.config.AbstractContainerConfig;
+import org.apache.shindig.config.ContainerConfigELResolver;
+import org.apache.shindig.config.ContainerConfigException;
+import org.apache.shindig.config.DynamicConfigProperty;
+import org.apache.shindig.expressions.Expressions;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ValueExpression;
+
+/**
+ * A fork of the class JsonContainerConfig, designed to override the loading of
container.js
+ *
+ * User: Minh Hoang TO - hoang281283(a)gmail.com
+ * Date: 1/10/11
+ * Time: 2:12 PM
+ */
+@Singleton
+public class GateInJsonContainerConfig extends AbstractContainerConfig {
+
+ private static final Logger LOG =
Logger.getLogger(GateInJsonContainerConfig.class.getName());
+ public static final char FILE_SEPARATOR = ',';
+ public static final String PARENT_KEY = "parent";
+ // TODO: Rename this to simply "container", gadgets.container is
unnecessary.
+ public static final String CONTAINER_KEY = "gadgets.container";
+
+ private final Map<String, Map<String, Object>> config;
+ private final Expressions expressions;
+
+ /**
+ * Creates a new configuration from files.
+ * @throws ContainerConfigException
+ */
+ @Inject
+ public GateInJsonContainerConfig((a)Named("shindig.containers.default") String
containers, Expressions expressions)
+ throws ContainerConfigException {
+ this.expressions = expressions;
+ config = createContainers(loadContainers(containers));
+ init();
+ }
+
+ /**
+ * Creates a new configuration from a JSON Object, for use in testing.
+ */
+ public GateInJsonContainerConfig(JSONObject json, Expressions expressions) {
+ this.expressions = expressions;
+ config = createContainers(json);
+ init();
+ }
+
+ /**
+ * Initializes the configuration. Called during construction.
+ */
+ protected void init() {
+ for (Map.Entry<String, Map<String, Object>> configEntry :
config.entrySet()) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> value = (Map<String, Object>)
evaluateAll(configEntry.getValue());
+ configEntry.setValue(value);
+ }
+ }
+
+ @Override
+ public Collection<String> getContainers() {
+ return Collections.unmodifiableSet(config.keySet());
+ }
+
+ @Override
+ public Map<String, Object> getProperties(String container) {
+ return config.get(container);
+ }
+
+ @Override
+ public Object getProperty(String container, String property) {
+ if (property.startsWith("${")) {
+ // An expression!
+ try {
+ ValueExpression expression = expressions.parse(property, Object.class);
+ return expression.getValue(createExpressionContext(container));
+ } catch (ELException e) {
+ return null;
+ }
+ }
+
+ Map<String, Object> containerData = config.get(container);
+ if (containerData == null) {
+ return null;
+ }
+ return containerData.get(property);
+ }
+
+ /**
+ * Initialize each container's configuration.
+ */
+ private Map<String, Map<String, Object>> createContainers(JSONObject json)
{
+ Map<String, Map<String, Object>> map = Maps.newHashMap();
+ for (String container : JSONObject.getNames(json)) {
+ ELContext context = createExpressionContext(container);
+ map.put(container, jsonToMap(json.optJSONObject(container), expressions,
context));
+ }
+
+ return map;
+ }
+
+ /**
+ * Make Expressions available to subclasses so they can create ELContexts
+ */
+ protected Expressions getExpressions() {
+ return expressions;
+ }
+
+ /**
+ * Protected to allow overriding.
+ */
+ protected ELContext createExpressionContext(String container) {
+ return getExpressions().newELContext(new ContainerConfigELResolver(this,
container));
+ }
+
+ /**
+ * Convert a JSON value to a configuration value.
+ */
+ private static Object jsonToConfig(Object json, Expressions expressions, ELContext
context) {
+ if (JSONObject.NULL.equals(json)) {
+ return null;
+ } else if (json instanceof CharSequence) {
+ return new DynamicConfigProperty(json.toString(), expressions, context);
+ } else if (json instanceof JSONArray) {
+ JSONArray jsonArray = (JSONArray) json;
+ List<Object> values = new ArrayList<Object>(jsonArray.length());
+ for (int i = 0, j = jsonArray.length(); i < j; ++i) {
+ values.add(jsonToConfig(jsonArray.opt(i), expressions, context));
+ }
+ return Collections.unmodifiableList(values);
+ } else if (json instanceof JSONObject) {
+ return jsonToMap((JSONObject) json, expressions, context);
+ }
+
+ // A (boxed) primitive.
+ return json;
+ }
+
+ private static Map<String, Object> jsonToMap(JSONObject json, Expressions
expressions, ELContext context) {
+ Map<String, Object> values = new HashMap<String, Object>(json.length(),
1);
+ for (String key : JSONObject.getNames(json)) {
+ Object val = jsonToConfig(json.opt(key), expressions, context);
+ if (val != null) {
+ values.put(key, val);
+ }
+ }
+ return Collections.unmodifiableMap(values);
+ }
+
+ /**
+ * Loads containers from directories recursively.
+ *
+ * Only files with a .js or .json extension will be loaded.
+ *
+ * @param files The files to examine.
+ * @throws ContainerConfigException
+ */
+ private void loadFiles(File[] files, JSONObject all) throws ContainerConfigException {
+ try {
+ for (File file : files) {
+ LOG.info("Reading container config: " + file.getName());
+ if (file.isDirectory()) {
+ loadFiles(file.listFiles(), all);
+ } else if (file.getName().toLowerCase(Locale.ENGLISH).endsWith(".js")
||
+
file.getName().toLowerCase(Locale.ENGLISH).endsWith(".json")) {
+ if (!file.exists()) {
+ throw new ContainerConfigException(
+ "The file '" + file.getAbsolutePath() + "'
doesn't exist.");
+ }
+ loadFromString(ResourceLoader.getContent(file), all);
+ } else {
+ if (LOG.isLoggable(Level.FINEST))
+ LOG.finest(file.getAbsolutePath() + " doesn't seem to be a JS or
JSON file.");
+ }
+ }
+ } catch (IOException e) {
+ throw new ContainerConfigException(e);
+ }
+ }
+
+ /**
+ * Loads resources recursively.
+ * @param files The base paths to look for container.xml
+ * @throws ContainerConfigException
+ */
+ private void loadResources(String[] files, JSONObject all) throws
ContainerConfigException {
+ try {
+ for (String entry : files) {
+ LOG.info("Reading container config: " + entry);
+ //final ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
+ //InputStream resourceInputStream = contextCl.getResourceAsStream(entry);
+ //String content = IOUtils.toString(resourceInputStream, "UTF-8");
+
+ GateInContainerConfigLoader currentLoader =
GateInGuiceServletContextListener.getCurrentLoader();
+ String content = currentLoader.loadContentAsString(entry, "UTF-8");
+ loadFromString(content, all);
+ }
+ } catch (IOException e) {
+ throw new ContainerConfigException(e);
+ }
+ }
+
+ /**
+ * Merges two JSON objects together (recursively), with values from "merge"
+ * replacing values in "base" to produce a new object.
+ *
+ * @param base The base object that values will be replaced into.
+ * @param merge The object to merge values from.
+ *
+ * @throws JSONException if the two objects can't be merged for some reason.
+ */
+ private JSONObject mergeObjects(JSONObject base, JSONObject merge)
+ throws JSONException {
+ // Clone the initial object (JSONObject doesn't support "clone").
+
+ JSONObject clone = new JSONObject(base, JSONObject.getNames(base));
+ // Walk parameter list for the merged object and merge recursively.
+ String[] fields = JSONObject.getNames(merge);
+ for (String field : fields) {
+ Object existing = clone.opt(field);
+ Object update = merge.get(field);
+ if (JSONObject.NULL.equals(existing) || JSONObject.NULL.equals(update)) {
+ // It's new custom config, not referenced in the prototype, or
+ // it's removing a pre-configured value.
+ clone.put(field, update);
+ } else {
+ // Merge if object type is JSONObject.
+ if (update instanceof JSONObject &&
+ existing instanceof JSONObject) {
+ clone.put(field, mergeObjects((JSONObject)existing,
+ (JSONObject)update));
+ } else {
+ // Otherwise we just overwrite it.
+ clone.put(field, update);
+ }
+ }
+ }
+ return clone;
+ }
+
+ /**
+ * Recursively merge values from parent objects in the prototype chain.
+ *
+ * @return The object merged with all parents.
+ *
+ * @throws ContainerConfigException If there is an invalid parent parameter
+ * in the prototype chain.
+ */
+ private JSONObject mergeParents(String container, JSONObject all)
+ throws ContainerConfigException, JSONException {
+ JSONObject base = all.getJSONObject(container);
+ if (DEFAULT_CONTAINER.equals(container)) {
+ return base;
+ }
+
+ String parent = base.optString(PARENT_KEY, DEFAULT_CONTAINER);
+ if (!all.has(parent)) {
+ throw new ContainerConfigException(
+ "Unable to locate parent '" + parent + "' required by
"
+ + base.getString(CONTAINER_KEY));
+ }
+ return mergeObjects(mergeParents(parent, all), base);
+ }
+
+ /**
+ * Processes a container file.
+ *
+ * @param json
+ * @throws ContainerConfigException
+ */
+ protected void loadFromString(String json, JSONObject all) throws
ContainerConfigException {
+ try {
+ JSONObject contents = new JSONObject(json);
+ JSONArray containers = contents.getJSONArray(CONTAINER_KEY);
+
+ for (int i = 0, j = containers.length(); i < j; ++i) {
+ // Copy the default object and produce a new one.
+ String container = containers.getString(i);
+ all.put(container, contents);
+ }
+ } catch (JSONException e) {
+ throw new ContainerConfigException(e);
+ }
+ }
+
+ /**
+ * Loads containers from the specified resource. Follows the same rules
+ * as {@code JsFeatureLoader.loadFeatures} for locating resources.
+ *
+ * @param path
+ * @throws ContainerConfigException
+ */
+ private JSONObject loadContainers(String path) throws ContainerConfigException {
+ JSONObject all = new JSONObject();
+ try {
+ for (String location : StringUtils.split(path, FILE_SEPARATOR)) {
+ if (location.startsWith("res://")) {
+ location = location.substring(6);
+ LOG.info("Loading resources from: " + location);
+ if (path.endsWith(".txt")) {
+ loadResources(ResourceLoader.getContent(location).split("[\r\n]+"),
all);
+ } else {
+ loadResources(new String[]{location}, all);
+ }
+ } else {
+ LOG.info("Loading files from: " + location);
+ File file = new File(location);
+ loadFiles(new File[]{file}, all);
+ }
+ }
+
+ // Now that all containers are loaded, we go back through them and merge
+ // recursively. This is done at startup to simplify lookups.
+ for (String container : JSONObject.getNames(all)) {
+ all.put(container, mergeParents(container, all));
+ }
+
+ return all;
+ } catch (IOException e) {
+ throw new ContainerConfigException(e);
+ } catch (JSONException e) {
+ throw new ContainerConfigException(e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return JsonSerializer.serialize(config);
+ }
+
+ private Object evaluateAll(Object value) {
+ if (value instanceof CharSequence) {
+ return value.toString();
+ } else if (value instanceof Map) {
+ ImmutableMap.Builder<Object, Object> newMap = ImmutableMap.builder();
+ for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
+ newMap.put(entry.getKey(), evaluateAll(entry.getValue()));
+ }
+
+ return newMap.build();
+ } else if (value instanceof List) {
+ ImmutableList.Builder<Object> newList = ImmutableList.builder();
+ for (Object entry : (List<?>) value){
+ newList.add(evaluateAll(entry));
+ }
+
+ return newList.build();
+ } else {
+ return value;
+ }
+ }
+}
\ No newline at end of file
Modified: portal/trunk/gadgets/server/src/main/webapp/WEB-INF/web.xml
===================================================================
--- portal/trunk/gadgets/server/src/main/webapp/WEB-INF/web.xml 2011-01-26 11:48:32 UTC
(rev 5820)
+++ portal/trunk/gadgets/server/src/main/webapp/WEB-INF/web.xml 2011-01-27 03:56:42 UTC
(rev 5821)
@@ -79,7 +79,8 @@
</filter-mapping>
<listener>
-
<listener-class>org.apache.shindig.common.servlet.GuiceServletContextListener</listener-class>
+
<!--<listener-class>org.apache.shindig.common.servlet.GuiceServletContextListener</listener-class>-->
+
<listener-class>org.exoplatform.portal.gadget.core.GateInGuiceServletContextListener</listener-class>
</listener>
<!-- Render a Gadget -->
Copied: portal/trunk/gadgets/server/src/main/webapp/containers (from rev 5820,
portal/branches/branch-GTNPORTAL-1745/gadgets/server/src/main/webapp/containers)
Copied: portal/trunk/gadgets/server/src/main/webapp/containers/default (from rev 5820,
portal/branches/branch-GTNPORTAL-1745/gadgets/server/src/main/webapp/containers/default)
Deleted: portal/trunk/gadgets/server/src/main/webapp/containers/default/container.js
===================================================================
---
portal/branches/branch-GTNPORTAL-1745/gadgets/server/src/main/webapp/containers/default/container.js 2011-01-26
11:48:32 UTC (rev 5820)
+++ portal/trunk/gadgets/server/src/main/webapp/containers/default/container.js 2011-01-27
03:56:42 UTC (rev 5821)
@@ -1,180 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- *
http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// Default container configuration. To change the configuration, you have two options:
-//
-// A. If you run the Java server: Create your own "myContainer.js" file and
-// modify the value in web.xml.
-//
-// B. If you run the PHP server: Create a myContainer.js, copy the contents of
container.js to it,
-// change
-// {"gadgets.container" : ["default"],
-// to
-// {"gadgets.container" : ["myContainer"],
-// And make your changes that you need to myContainer.js.
-// Just make sure on the iframe URL you specify &container=myContainer
-// for it to use that config.
-//
-// All configurations will automatically inherit values from this
-// config, so you only need to provide configuration for items
-// that you require explicit special casing for.
-//
-// Please namespace your attributes using the same conventions
-// as you would for javascript objects, e.g. gadgets.features
-// rather than "features".
-
-// NOTE: Please _don't_ leave trailing commas because the php json parser
-// errors out on this.
-
-// Container must be an array; this allows multiple containers
-// to share configuration.
-{"gadgets.container" : ["default"],
-
-// Set of regular expressions to validate the parent parameter. This is
-// necessary to support situations where you want a single container to support
-// multiple possible host names (such as for localized domains, such as
-// <
language>.example.org. If left as null, the parent parameter will be
-// ignored; otherwise, any requests that do not include a parent
-// value matching this set will return a 404 error.
-"gadgets.parent" : null,
-
-// Should all gadgets be forced on to a locked domain?
-"gadgets.lockedDomainRequired" : false,
-
-// DNS domain on which gadgets should render.
-"gadgets.lockedDomainSuffix" : "-a.example.com:8080",
-
-// Various urls generated throughout the code base.
-// iframeBaseUri will automatically have the host inserted
-// if locked domain is enabled and the implementation supports it.
-// query parameters will be added.
-"gadgets.iframeBaseUri" : "/eXoGadgetServer/gadgets/ifr",
-
-// jsUriTemplate will have %host% and %js% substituted.
-// No locked domain special cases, but jsUriTemplate must
-// never conflict with a lockedDomainSuffix.
-"gadgets.jsUriTemplate" :
"http://%host%/eXoGadgetServer/gadgets/js/%js%",
-
-// Callback URL. Scheme relative URL for easy switch between https/http.
-"gadgets.oauthGadgetCallbackTemplate" :
"//%host%/eXoGadgetServer/gadgets/oauthcallback",
-
-// Use an insecure security token by default
-"gadgets.securityTokenType" : "secure",
-"gadgets.securityTokenKeyFile" : "key.txt",
-
-"gadgets.signingKeyFile" : "oauthkey.pem",
-"gadgets.signingKeyName" : "mytestkey",
-
-"gadgets.signedFetchDomain" : "eXo",
-// Config param to load Opensocial data for social
-// preloads in data pipelining. %host% will be
-// substituted with the current host.
-"gadgets.osDataUri" : "http://%host%/social/rpc",
-
-// Uncomment these to switch to a secure version
-//
-//"gadgets.securityTokenType" : "secure",
-//"gadgets.securityTokenKeyFile" : "/path/to/key/file.txt",
-
-"gadgets.content-rewrite" : {
- "include-urls": ".*",
- "exclude-urls": "",
- "include-tags": ["link", "script", "embed",
"img", "style"],
- "expires": "86400",
- "proxy-url": "/eXoGadgetServer/gadgets/proxy?url=",
- "concat-url": "/eXoGadgetServer/gadgets/concat?"
-},
-
-// This config data will be passed down to javascript. Please
-// configure your object using the feature name rather than
-// the javascript name.
-
-// Only configuration for required features will be used.
-// See individual feature.xml files for configuration details.
-"gadgets.features" : {
- "core.io" : {
- // Note: /proxy is an open proxy. Be careful how you expose this!
- "proxyUrl" :
"http://%host%/eXoGadgetServer/gadgets/proxy?refresh=%refresh%&url=%url%",
- "jsonProxyUrl" :
"http://%host%/eXoGadgetServer/gadgets/makeRequest"
- },
- "views" : {
- "home" : {
- "isOnlyVisible" : false,
- "urlTemplate" :
"http://%host%/eXoGadgetServer/gadgets/home?{var}",
- "aliases": ["DASHBOARD", "default"]
- },
- "canvas" : {
- "isOnlyVisible" : true,
- "urlTemplate" :
"http://%host%/eXoGadgetServer/gadgets/canvas?{var}",
- "aliases" : ["FULL_PAGE"]
- }
- },
- "rpc" : {
- // Path to the relay file. Automatically appended to the parent
- /// parameter if it passes input validation and is not null.
- // This should never be on the same host in a production environment!
- // Only use this for TESTING!
- "parentRelayUrl" :
"/eXoGadgetServer/gadgets/files/container/rpc_relay.html",
-
- // If true, this will use the legacy ifpc wire format when making rpc
- // requests.
- "useLegacyProtocol" : false
- },
- // Skin defaults
- "skins" : {
- "properties" : {
- "BG_COLOR": "",
- "BG_IMAGE": "",
- "BG_POSITION": "",
- "BG_REPEAT": "",
- "FONT_COLOR": "",
- "ANCHOR_COLOR": ""
- }
- },
- "opensocial-0.8" : {
- // Path to fetch opensocial data from
- // Must be on the same domain as the gadget rendering server
- "path" : "http://%host%/social",
- "domain" : "shindig",
- "enableCaja" : false,
- "supportedFields" : {
- "person" : ["id", {"name" : ["familyName",
"givenName", "unstructured"]}, "thumbnailUrl",
"profileUrl"],
- "activity" : ["id", "title"]
- }
- },
- "osapi.services" : {
- // Specifying a binding to "container.listMethods" instructs osapi to
dynamicaly introspect the services
- // provided by the container and delay the gadget onLoad handler until that
introspection is
- // complete.
- // Alternatively a container can directly configure services here rather than having
them
- // introspected. Simply list out the available servies and omit
"container.listMethods" to
- // avoid the initialization delay caused by gadgets.rpc
- // E.g. "gadgets.rpc" : ["activities.requestCreate",
"messages.requestSend", "requestShareApp",
"requestPermission"]
- "gadgets.rpc" : ["container.listMethods"]
- },
-// "osapi" : {
-// // The endpoints to query for available JSONRPC/REST services
-// "endPoints" : [ "http://%host%/social/rpc",
"http://%host%/gadgets/api/rpc" ]
-// },
- "osml": {
- // OSML library resource. Can be set to null or the empty string to disable OSML
- // for a container.
- "library": ""
- }
-}}
Copied: portal/trunk/gadgets/server/src/main/webapp/containers/default/container.js (from
rev 5820,
portal/branches/branch-GTNPORTAL-1745/gadgets/server/src/main/webapp/containers/default/container.js)
===================================================================
--- portal/trunk/gadgets/server/src/main/webapp/containers/default/container.js
(rev 0)
+++ portal/trunk/gadgets/server/src/main/webapp/containers/default/container.js 2011-01-27
03:56:42 UTC (rev 5821)
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *
http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Default container configuration. To change the configuration, you have two options:
+//
+// A. If you run the Java server: Create your own "myContainer.js" file and
+// modify the value in web.xml.
+//
+// B. If you run the PHP server: Create a myContainer.js, copy the contents of
container.js to it,
+// change
+// {"gadgets.container" : ["default"],
+// to
+// {"gadgets.container" : ["myContainer"],
+// And make your changes that you need to myContainer.js.
+// Just make sure on the iframe URL you specify &container=myContainer
+// for it to use that config.
+//
+// All configurations will automatically inherit values from this
+// config, so you only need to provide configuration for items
+// that you require explicit special casing for.
+//
+// Please namespace your attributes using the same conventions
+// as you would for javascript objects, e.g. gadgets.features
+// rather than "features".
+
+// NOTE: Please _don't_ leave trailing commas because the php json parser
+// errors out on this.
+
+// Container must be an array; this allows multiple containers
+// to share configuration.
+{"gadgets.container" : ["default"],
+
+// Set of regular expressions to validate the parent parameter. This is
+// necessary to support situations where you want a single container to support
+// multiple possible host names (such as for localized domains, such as
+// <
language>.example.org. If left as null, the parent parameter will be
+// ignored; otherwise, any requests that do not include a parent
+// value matching this set will return a 404 error.
+"gadgets.parent" : null,
+
+// Should all gadgets be forced on to a locked domain?
+"gadgets.lockedDomainRequired" : false,
+
+// DNS domain on which gadgets should render.
+"gadgets.lockedDomainSuffix" : "-a.example.com:8080",
+
+// Various urls generated throughout the code base.
+// iframeBaseUri will automatically have the host inserted
+// if locked domain is enabled and the implementation supports it.
+// query parameters will be added.
+"gadgets.iframeBaseUri" : "/eXoGadgetServer/gadgets/ifr",
+
+// jsUriTemplate will have %host% and %js% substituted.
+// No locked domain special cases, but jsUriTemplate must
+// never conflict with a lockedDomainSuffix.
+"gadgets.jsUriTemplate" :
"http://%host%/eXoGadgetServer/gadgets/js/%js%",
+
+// Callback URL. Scheme relative URL for easy switch between https/http.
+"gadgets.oauthGadgetCallbackTemplate" :
"//%host%/eXoGadgetServer/gadgets/oauthcallback",
+
+// Use an insecure security token by default
+"gadgets.securityTokenType" : "secure",
+"gadgets.securityTokenKeyFile" : "key.txt",
+
+"gadgets.signingKeyFile" : "oauthkey.pem",
+"gadgets.signingKeyName" : "mytestkey",
+
+"gadgets.signedFetchDomain" : "eXo",
+// Config param to load Opensocial data for social
+// preloads in data pipelining. %host% will be
+// substituted with the current host.
+"gadgets.osDataUri" : "http://%host%/social/rpc",
+
+// Uncomment these to switch to a secure version
+//
+//"gadgets.securityTokenType" : "secure",
+//"gadgets.securityTokenKeyFile" : "/path/to/key/file.txt",
+
+"gadgets.content-rewrite" : {
+ "include-urls": ".*",
+ "exclude-urls": "",
+ "include-tags": ["link", "script", "embed",
"img", "style"],
+ "expires": "86400",
+ "proxy-url": "/eXoGadgetServer/gadgets/proxy?url=",
+ "concat-url": "/eXoGadgetServer/gadgets/concat?"
+},
+
+// This config data will be passed down to javascript. Please
+// configure your object using the feature name rather than
+// the javascript name.
+
+// Only configuration for required features will be used.
+// See individual feature.xml files for configuration details.
+"gadgets.features" : {
+ "core.io" : {
+ // Note: /proxy is an open proxy. Be careful how you expose this!
+ "proxyUrl" :
"http://%host%/eXoGadgetServer/gadgets/proxy?refresh=%refresh%&url=%url%",
+ "jsonProxyUrl" :
"http://%host%/eXoGadgetServer/gadgets/makeRequest"
+ },
+ "views" : {
+ "home" : {
+ "isOnlyVisible" : false,
+ "urlTemplate" :
"http://%host%/eXoGadgetServer/gadgets/home?{var}",
+ "aliases": ["DASHBOARD", "default"]
+ },
+ "canvas" : {
+ "isOnlyVisible" : true,
+ "urlTemplate" :
"http://%host%/eXoGadgetServer/gadgets/canvas?{var}",
+ "aliases" : ["FULL_PAGE"]
+ }
+ },
+ "rpc" : {
+ // Path to the relay file. Automatically appended to the parent
+ /// parameter if it passes input validation and is not null.
+ // This should never be on the same host in a production environment!
+ // Only use this for TESTING!
+ "parentRelayUrl" :
"/eXoGadgetServer/gadgets/files/container/rpc_relay.html",
+
+ // If true, this will use the legacy ifpc wire format when making rpc
+ // requests.
+ "useLegacyProtocol" : false
+ },
+ // Skin defaults
+ "skins" : {
+ "properties" : {
+ "BG_COLOR": "",
+ "BG_IMAGE": "",
+ "BG_POSITION": "",
+ "BG_REPEAT": "",
+ "FONT_COLOR": "",
+ "ANCHOR_COLOR": ""
+ }
+ },
+ "opensocial-0.8" : {
+ // Path to fetch opensocial data from
+ // Must be on the same domain as the gadget rendering server
+ "path" : "http://%host%/social",
+ "domain" : "shindig",
+ "enableCaja" : false,
+ "supportedFields" : {
+ "person" : ["id", {"name" : ["familyName",
"givenName", "unstructured"]}, "thumbnailUrl",
"profileUrl"],
+ "activity" : ["id", "title"]
+ }
+ },
+ "osapi.services" : {
+ // Specifying a binding to "container.listMethods" instructs osapi to
dynamicaly introspect the services
+ // provided by the container and delay the gadget onLoad handler until that
introspection is
+ // complete.
+ // Alternatively a container can directly configure services here rather than having
them
+ // introspected. Simply list out the available servies and omit
"container.listMethods" to
+ // avoid the initialization delay caused by gadgets.rpc
+ // E.g. "gadgets.rpc" : ["activities.requestCreate",
"messages.requestSend", "requestShareApp",
"requestPermission"]
+ "gadgets.rpc" : ["container.listMethods"]
+ },
+// "osapi" : {
+// // The endpoints to query for available JSONRPC/REST services
+// "endPoints" : [ "http://%host%/social/rpc",
"http://%host%/gadgets/api/rpc" ]
+// },
+ "osml": {
+ // OSML library resource. Can be set to null or the empty string to disable OSML
+ // for a container.
+ "library": ""
+ }
+}}
Modified:
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_en.properties
===================================================================
---
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_en.properties 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_en.properties 2011-01-27
03:56:42 UTC (rev 5821)
@@ -1407,6 +1407,7 @@
UIGadget.tooltip.Unmaximize=Restore Down
UIGadget.tooltip.editGadget=Edit Gadget
UIGadget.tooltip.deleteGadget=Delete Gadget
+UIGadget.message.isLossData=This gadget may be deleted from database or there is database
error that prevent to read content of gadget
UIListPermissionSelectorPopup.title.ListPermissionSelector=Select Permission
Modified:
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_vi.properties
===================================================================
---
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_vi.properties 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_vi.properties 2011-01-27
03:56:42 UTC (rev 5821)
@@ -1342,6 +1342,7 @@
UIGadget.tooltip.Unmaximize=Thu nhỏ cửa sổ
UIGadget.tooltip.editGadget=Sửa Gadget
UIGadget.tooltip.deleteGadget=Xóa Gadget
+UIGadget.message.isLossData=Gadget này có thể đã bị xóa khỏi cơ sở dữ liệu hoặc việc đọc
gadget từ cơ sở dữ liệu xảy ra lỗi
UIListPermissionSelectorPopup.title.ListPermissionSelector=Lựa chọn quyền
UIUserToolBarDashboard.page.ClickAndType=Nhấp chuột và điền tên trang
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/web.xml
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/web.xml 2011-01-26 11:48:32 UTC (rev
5820)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/web.xml 2011-01-27 03:56:42 UTC (rev
5821)
@@ -182,9 +182,6 @@
<listener-class>org.exoplatform.web.GenericHttpListener</listener-class>
</listener>
<listener>
-
<listener-class>org.exoplatform.portal.application.PortalSessionListener</listener-class>
- </listener>
- <listener>
<listener-class>org.exoplatform.services.security.web.JAASConversationStateListener</listener-class>
</listener>
<!-- ================================================================== -->
Modified:
portal/trunk/web/portal/src/main/webapp/groovy/portal/webui/application/UIGadget.gtmpl
===================================================================
---
portal/trunk/web/portal/src/main/webapp/groovy/portal/webui/application/UIGadget.gtmpl 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/web/portal/src/main/webapp/groovy/portal/webui/application/UIGadget.gtmpl 2011-01-27
03:56:42 UTC (rev 5821)
@@ -2,25 +2,32 @@
import org.exoplatform.web.application.JavascriptManager;
import org.exoplatform.portal.webui.application.GadgetUtil;
- def rcontext = _ctx.getRequestContext();
- JavascriptManager jsmanager = rcontext.getJavascriptManager();
- def hostName = GadgetUtil.getRelGadgetServerUrl();
- def url = uicomponent.getUrl();
- def metadata = uicomponent.getMetadata();
- def posX = uicomponent.getProperties().getIntValue("locationX") +
"px";
- def posY = uicomponent.getProperties().getIntValue("locationY") +
"px";
- def zIndex = uicomponent.getProperties().getIntValue("zIndex");
- def id = uicomponent.getId();
- def isDev = uicomponent.isGadgetDeveloper();
- def noCache = uicomponent.isNoCache();
- def isDebug = uicomponent.isDebug();
- def view = uicomponent.getView();
- def userPref = uicomponent.getUserPref();
- jsmanager.importJavascript("eXo.gadget.UIGadget");
- rcontext.getJavascriptManager().addCustomizedOnLoadScript("eXo.gadget.UIGadget.confirmDeleteGadget
= '" + _ctx.appRes("UIGadgetContainerManagement.confirm.DeleteGadget")
+ "';");
- jsmanager.addCustomizedOnLoadScript("eXo.gadget.UIGadget.createGadget('$url','content-$id',
$metadata, $userPref, '$view', '$hostName', " + (isDev ? 1 : 0)
- + ", " + (isDebug ? 1 : 0) + ",
" + (noCache ? 1 : 0) + ");");
-
+ def rcontext = _ctx.getRequestContext();
+ JavascriptManager jsmanager = rcontext.getJavascriptManager();
+ def hostName = GadgetUtil.getRelGadgetServerUrl();
+ def url = null;
+ def metadata = "";
+ def posX = uicomponent.getProperties().getIntValue("locationX") +
"px";
+ def posY = uicomponent.getProperties().getIntValue("locationY") +
"px";
+ def zIndex = uicomponent.getProperties().getIntValue("zIndex");
+ def id = uicomponent.getId() != null ? uicomponent.getId() : "UIGadget";
+ def isDev = uicomponent.isGadgetDeveloper();
+ def noCache = uicomponent.isNoCache();
+ def isDebug = uicomponent.isDebug();
+ def view = uicomponent.getView();
+ def userPref = null;
+
+ def isLossData = uicomponent.isLossData();
+ if(!isLossData) {
+ url = uicomponent.getUrl();
+ metadata = uicomponent.getMetadata();
+ userPref = uicomponent.getUserPref();
+ jsmanager.importJavascript("eXo.gadget.UIGadget");
+
rcontext.getJavascriptManager().addCustomizedOnLoadScript("eXo.gadget.UIGadget.confirmDeleteGadget
= '" + _ctx.appRes("UIGadgetContainerManagement.confirm.DeleteGadget")
+ "';");
+
jsmanager.addCustomizedOnLoadScript("eXo.gadget.UIGadget.createGadget('$url','content-$id',
$metadata, $userPref, '$view', '$hostName', " + (isDev ? 1 : 0)
+ + ", " + (isDebug ? 1 : 0) +
", " + (noCache ? 1 : 0) + ");");
+ }
+
boolean isMini =
Boolean.parseBoolean(uicomponent.getProperties().get("minimized"));
String miniTitle = _ctx.appRes("UIGadget.tooltip.Minimize");
String unminiTitle = _ctx.appRes("UIGadget.tooltip.Unminimize");
@@ -43,7 +50,7 @@
<div class="EditGadget IconControl"
onclick="eXo.gadget.UIGadget.editGadget('$id')"
onmousedown="event.cancelBubble=true;"
title="<%=_ctx.appRes("UIGadget.tooltip.editGadget")%>"><span></span></div>
<% } %>
<div
class="GadgetDragHandleArea"><span></span></div>
- <div class="GadgetTitle" style="display: none; float: none; width:
auto; margin-right: 75px"><%= uicomponent.getApplicationName()
%></div>
+ <div class="GadgetTitle" style="display: <%=isLossData ?
"block" : "none"; %> ; float: none; width: auto; margin-right:
75px"><%= uicomponent.getApplicationName() %></div>
</div>
</div>
</div>
@@ -57,8 +64,12 @@
</div>
<div class="MLGadget">
<div class="MRGadget">
- <div id="content-$id" class="MCGadget"></div>
- </div>
+ <% if(isLossData) {%>
+ <div id="content-$id"
class="MCGadget"><%=_ctx.appRes("UIGadget.message.isLossData")%></div>
+ <% } else {%>
+ <div id="content-$id"
class="MCGadget"></div>
+ <% } %>
+ </div>
</div>
<div class="BLGadget">
<div class="BRGadget">
Modified:
portal/trunk/web/portal/src/main/webapp/groovy/portal/webui/portal/UILanguageSelector.gtmpl
===================================================================
---
portal/trunk/web/portal/src/main/webapp/groovy/portal/webui/portal/UILanguageSelector.gtmpl 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/web/portal/src/main/webapp/groovy/portal/webui/portal/UILanguageSelector.gtmpl 2011-01-27
03:56:42 UTC (rev 5821)
@@ -48,7 +48,14 @@
<%
for(opt in options) {
String itemSelected = "NormalItem";
- if (opt.isSelected()) itemSelected = "SelectedItem";
+ if (opt.isSelected()) {
+ def setSelected = "eXo.webui.UIItemSelector.SelectedItem = new
Object();";
+ setSelected += "eXo.webui.UIItemSelector.SelectedItem.component =
'$selector.name';";
+ setSelected += "eXo.webui.UIItemSelector.SelectedItem.option =
'$opt.value';";
+
+ rcontext.getJavascriptManager().addCustomizedOnLoadScript(setSelected);
+ itemSelected = "SelectedItem";
+ }
String onclickOption = "eXo.webui.UIItemSelector.onClickOption(this,
'$uicomponent.name', '$selector.name', '$opt.value')";
%>
<div class="$itemSelected"
onclick="$onclickOption">
@@ -102,4 +109,4 @@
</div>
</div>
</div>
-</div>
\ No newline at end of file
+</div>
Modified:
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/UIFormInputSet.java
===================================================================
---
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/UIFormInputSet.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/UIFormInputSet.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -167,34 +167,34 @@
UIForm uiForm = getAncestorOfType(UIForm.class);
for (UIComponent inputEntry : getChildren())
{
- if (inputEntry.isRendered())
+ if (inputEntry instanceof UIFormInputBase)
{
- String label;
- try
+ if (inputEntry.isRendered())
{
- label = uiForm.getLabel(res, inputEntry.getId());
- if (inputEntry instanceof UIFormInputBase)
- ((UIFormInputBase)inputEntry).setLabel(label);
+ UIFormInputBase formInputBase = (UIFormInputBase) inputEntry;
+ String label;
+ if (formInputBase.getLabel() != null)
+ {
+ label = uiForm.getLabel(res, formInputBase.getLabel());
+ }
+ else
+ {
+ label = uiForm.getLabel(res, formInputBase.getId());
+ }
+ w.write("<tr>");
+ w.write("<td class=\"FieldLabel\">");
+
+ // if missing resource and the label hasn't been set before, don't
print out the label.
+ if (formInputBase.getLabel() != null || (label != formInputBase.getId()))
+ {
+ w.write(label);
+ }
+ w.write("</td>");
+ w.write("<td class=\"FieldComponent\">");
+ renderUIComponent(formInputBase);
+ w.write("</td>");
+ w.write("</tr>");
}
- catch (MissingResourceException ex)
- {
- //label = " " ;
- label = inputEntry.getName();
- System.err.println("\n " + uiForm.getId() + ".label."
+ inputEntry.getId() + " not found value");
- }
- w.write("<tr>");
- w.write("<td class=\"FieldLabel\">");
-
- // if missing resource, don't print out the label.
- if(!label.equals(inputEntry.getName()))
- {
- w.write(label);
- }
- w.write("</td>");
- w.write("<td class=\"FieldComponent\">");
- renderUIComponent(inputEntry);
- w.write("</td>");
- w.write("</tr>");
}
}
w.write("</table>");
Modified:
portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component/UIAddGadgetForm.java
===================================================================
---
portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component/UIAddGadgetForm.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component/UIAddGadgetForm.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -97,14 +97,12 @@
//TODO make sure it's an rss feed
// TODO make sure that we did not add it already
uiGadget = uiForm.createUIComponent(context, UIGadget.class, null, null);
- uiGadget.setState(new
TransientApplicationState<org.exoplatform.portal.pom.spi.gadget.Gadget>(gadget.getName()));
- String params = "{'rssurl':'" + url +
"'}";
+ org.exoplatform.portal.pom.spi.gadget.Gadget contentState = new
org.exoplatform.portal.pom.spi.gadget.Gadget();
+ contentState.addUserPref("{'rssurl':'" + url +
"'}");
+ TransientApplicationState<org.exoplatform.portal.pom.spi.gadget.Gadget>
applicationState = new
TransientApplicationState<org.exoplatform.portal.pom.spi.gadget.Gadget>(gadget.getName(),
contentState);
- // Julien : I commented those 2 lines
- // we need to save the same way it is done in the UIGadget clas
- // UserGadgetStorage userGadgetStorage =
uiForm.getApplicationComponent(UserGadgetStorage.class);
- // userGadgetStorage.save(Util.getPortalRequestContext().getRemoteUser(),
gadget.getName(), "" + url.hashCode(), UIGadget.PREF_KEY, params);
+ uiGadget.setState(applicationState);
}
uiContainer.addUIGadget(uiGadget, 0, 0);
Modified:
portal/trunk/webui/framework/src/main/java/org/exoplatform/webui/config/Param.java
===================================================================
---
portal/trunk/webui/framework/src/main/java/org/exoplatform/webui/config/Param.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/framework/src/main/java/org/exoplatform/webui/config/Param.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -64,36 +64,41 @@
public Object getMapXMLObject(WebuiRequestContext context) throws Exception
{
- if (object != null)
- return object;
- ResourceResolver resolver = context.getResourceResolver(value);
- InputStream is = resolver.getInputStream(value);
- object = XMLObject.getObject(is);
- is.close();
+ if(object == null)
+ {
+ synchronized (this)
+ {
+ if(object == null)
+ {
+ ResourceResolver resolver = context.getResourceResolver(value);
+ InputStream is = resolver.getInputStream(value);
+ object = XMLObject.getObject(is);
+ is.close();
+ }
+ }
+ }
return object;
}
@SuppressWarnings("unchecked")
public Object getMapGroovyObject(WebuiRequestContext context) throws Exception
{
- try
+ if(object == null)
{
- if (object != null)
- return object;
- ResourceResolver resolver = context.getResourceResolver(value);
- InputStream is = resolver.getInputStream(value);
- //TODO if is == null throw an exception saying the it's impossible to find
the file
- Binding binding = new Binding();
- GroovyShell shell = new
GroovyShell(Thread.currentThread().getContextClassLoader(), binding);
- object = shell.evaluate(is);
- is.close();
- return object;
+ synchronized (this)
+ {
+ if(object == null)
+ {
+ ResourceResolver resolver = context.getResourceResolver(value);
+ InputStream is = resolver.getInputStream(value);
+ Binding binding = new Binding();
+ GroovyShell shell = new
GroovyShell(Thread.currentThread().getContextClassLoader(), binding);
+ object = shell.evaluate(is);
+ is.close();
+ }
+ }
}
- catch (Exception e)
- {
- log.error("A problem in the groovy script : " + value, e);
- throw e;
- }
+ return object;
}
public Object getFreshObject(WebuiRequestContext context) throws Exception
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalRequestContext.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -161,7 +161,8 @@
cacheLevel_ = cache;
}
- requestURI_ = URLDecoder.decode(req.getRequestURI(), "UTF-8");
+ requestURI_ = req.getRequestURI();
+ String decodedURI = URLDecoder.decode(requestURI_, "UTF-8");
// req.getPathInfo will already have the encoding set from the server.
// We need to use the UTF-8 value since this is how we store the portal name.
@@ -170,7 +171,7 @@
String contextPath = URLDecoder.decode(req.getContextPath(), "UTF-8");
String pathInfo = "/";
if (requestURI_.length() > servletPath.length() + contextPath.length())
- pathInfo = requestURI_.substring(servletPath.length() + contextPath.length());
+ pathInfo = decodedURI.substring(servletPath.length() + contextPath.length());
int colonIndex = pathInfo.indexOf("/", 1);
if (colonIndex < 0)
@@ -180,13 +181,13 @@
portalOwner_ = pathInfo.substring(1, colonIndex);
nodePath_ = pathInfo.substring(colonIndex, pathInfo.length());
- portalURI = requestURI_.substring(0, requestURI_.lastIndexOf(nodePath_)) +
"/";
+ portalURI = decodedURI.substring(0, decodedURI.lastIndexOf(nodePath_)) +
"/";
- if (requestURI_.indexOf("/public/") >= 0)
+ if (decodedURI.indexOf("/public/") >= 0)
{
accessPath = PUBLIC_ACCESS;
}
- else if (requestURI_.indexOf("/private/") >= 0)
+ else if (decodedURI.indexOf("/private/") >= 0)
{
accessPath = PRIVATE_ACCESS;
}
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalSessionListener.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalSessionListener.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/application/PortalSessionListener.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -19,31 +19,36 @@
package org.exoplatform.portal.application;
-import org.exoplatform.container.ExoContainer;
-import org.exoplatform.container.PortalContainer;
-import org.exoplatform.container.web.AbstractHttpSessionListener;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
-import org.exoplatform.web.WebAppController;
import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
/**
+ * This session listener was created for purpose of expiring the portal session stored in
the StateManager
+ * and removes the WindowInfos object from the WindowInfosContainer container
+ * <p>
* Created by The eXo Platform SAS
* Date: Jan 25, 2003
* Time: 5:25:52 PM
+ *
+ * @deprecated Currently we do not store anything outside of the session,
+ * that's why we do not need to clean anything when a session is destroyed.
*/
-public class PortalSessionListener extends AbstractHttpSessionListener
+@Deprecated
+public class PortalSessionListener implements HttpSessionListener
{
- protected static Log log =
ExoLogger.getLogger("portal:PortalSessionListener");
+ protected static Log log =
ExoLogger.getLogger("portal.PortalSessionListener");
public PortalSessionListener()
{
+ log.debug("This session listener is not useful anymore and it is left empty
for now to be compatible with older versions");
}
@Override
- protected void onSessionDestroyed(ExoContainer container, HttpSessionEvent event)
+ public void sessionCreated(HttpSessionEvent se)
{
}
@@ -63,29 +68,7 @@
*
*/
@Override
- protected void onSessionCreated(ExoContainer container, HttpSessionEvent event)
+ public void sessionDestroyed(HttpSessionEvent se)
{
- try
- {
- if (log.isInfoEnabled())
- log.info("Destroy session from '" + container == null ?
"unknown" : ((PortalContainer)container).getName()
- + "' portal");
- WebAppController controller =
(WebAppController)container.getComponentInstanceOfType(WebAppController.class);
- PortalApplication portalApp =
controller.getApplication(PortalApplication.PORTAL_APPLICATION_ID);
- portalApp.getStateManager().expire(event.getSession().getId(), portalApp);
- }
- catch (Exception ex)
- {
- log.error("Error while destroying a portal session", ex);
- }
}
-
- /**
- * @see
org.exoplatform.container.web.AbstractHttpSessionListener#requirePortalEnvironment()
- */
- @Override
- protected boolean requirePortalEnvironment()
- {
- return true;
- }
}
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIGadget.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIGadget.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIGadget.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -260,25 +260,6 @@
}
}
- @Override
- public boolean isRendered()
- {
- try
- {
- DataStorage service = getApplicationComponent(DataStorage.class);
- service.load(state, ApplicationType.GADGET);
- if (getApplication() == null)
- {
- throw new Exception();
- }
- }
- catch (Exception e)
- {
- return false;
- }
- return super.isRendered();
- }
-
public boolean isLossData()
{
try
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIPortletForm.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIPortletForm.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIPortletForm.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -22,8 +22,8 @@
import org.exoplatform.commons.utils.ExceptionUtil;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.pc.ExoPortletState;
-import org.exoplatform.portal.pom.spi.portlet.Preference;
import org.exoplatform.portal.pom.spi.portlet.Portlet;
+import org.exoplatform.portal.pom.spi.portlet.Preference;
import org.exoplatform.portal.pom.spi.wsrp.WSRP;
import org.exoplatform.portal.pom.spi.wsrp.WSRPPortletStateType;
import org.exoplatform.portal.portlet.PortletExceptionHandleService;
@@ -45,22 +45,15 @@
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.Event.Phase;
import org.exoplatform.webui.event.EventListener;
-import org.exoplatform.webui.form.UIFormCheckBoxInput;
-import org.exoplatform.webui.form.UIFormInputIconSelector;
-import org.exoplatform.webui.form.UIFormInputInfo;
-import org.exoplatform.webui.form.UIFormInputSet;
-import org.exoplatform.webui.form.UIFormStringInput;
-import org.exoplatform.webui.form.UIFormTabPane;
-import org.exoplatform.webui.form.UIFormTextAreaInput;
+import org.exoplatform.webui.form.*;
import org.exoplatform.webui.form.validator.ExpressionValidator;
import org.exoplatform.webui.form.validator.MandatoryValidator;
import org.exoplatform.webui.form.validator.StringLengthValidator;
import org.exoplatform.webui.organization.UIListPermissionSelector;
import
org.exoplatform.webui.organization.UIListPermissionSelector.EmptyIteratorValidator;
import org.gatein.pc.api.Mode;
-import org.gatein.pc.api.PortletContext;
-import org.gatein.pc.api.PortletInvoker;
import org.gatein.pc.api.StatefulPortletContext;
+import org.gatein.pc.api.info.PreferenceInfo;
import org.gatein.pc.api.invocation.RenderInvocation;
import org.gatein.pc.api.invocation.response.ErrorResponse;
import org.gatein.pc.api.invocation.response.FragmentResponse;
@@ -68,23 +61,12 @@
import org.gatein.pc.api.spi.InstanceContext;
import org.gatein.pc.api.state.AccessMode;
import org.gatein.pc.api.state.PropertyChange;
-import org.gatein.pc.portlet.impl.spi.AbstractClientContext;
-import org.gatein.pc.portlet.impl.spi.AbstractPortalContext;
-import org.gatein.pc.portlet.impl.spi.AbstractSecurityContext;
-import org.gatein.pc.portlet.impl.spi.AbstractServerContext;
-import org.gatein.pc.portlet.impl.spi.AbstractUserContext;
-import org.gatein.pc.portlet.impl.spi.AbstractWindowContext;
+import org.gatein.pc.portlet.impl.spi.*;
import javax.portlet.PortletMode;
import javax.servlet.http.Cookie;
+import java.util.*;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.ResourceBundle;
-
/** Author : Nhu Dinh Thuan nhudinhthuan(a)yahoo.com Jun 8, 2006 */
@ComponentConfigs({
@ComponentConfig(lifecycle = UIFormLifecycle.class, template =
"system:/groovy/portal/webui/portal/UIPortletForm.gtmpl", events = {
@@ -115,7 +97,7 @@
addValidator(MandatoryValidator.class).setEditable(false)).
addUIFormInput(new UIFormStringInput("windowId", "windowId",
null).setEditable(false)).*/
addUIFormInput(new UIFormInputInfo("displayName",
"displayName", null)).addUIFormInput(
- new UIFormStringInput("title", "title",
null).addValidator(StringLengthValidator.class, 3,
60).addValidator(ExpressionValidator.class, "[^\\<\\>]*",
+ new UIFormStringInput("title", "title",
null).addValidator(StringLengthValidator.class, 3,
60).addValidator(ExpressionValidator.class, "[^\\<\\>]*",
"UIPortletForm.msg.InvalidPortletTitle"))
.addUIFormInput(
new UIFormStringInput("width", "width",
null).addValidator(ExpressionValidator.class, "(^([1-9]\\d*)px$)?",
@@ -226,7 +208,7 @@
{
content = fragmentResponse.getContent();
}
-
+
}
else
{
@@ -262,7 +244,7 @@
}
portletContent.setLength(0);
-
+
portletContent.append(content);
}
catch (Throwable ex)
@@ -288,40 +270,59 @@
getChild(UIFormInputIconSelector.class).setSelectedIcon(icon);
getChild(UIFormInputThemeSelector.class).getChild(UIItemThemeSelector.class).setSelectedTheme(
uiPortlet.getSuitedTheme(null));
- WebuiRequestContext contextres = WebuiRequestContext.getCurrentInstance();
- ResourceBundle res = contextres.getApplicationResourceBundle();
if (hasEditMode())
{
uiPortlet.setCurrentPortletMode(PortletMode.EDIT);
}
else
{
+ Map<String, String> portletPreferenceMaps = new HashMap<String,
String>();
+ org.gatein.pc.api.Portlet portlet = uiPortlet.getProducedOfferedPortlet();
+ Set<String> keySet = portlet.getInfo().getPreferences().getKeys();
- //
+ for (String key : keySet)
+ {
+ PreferenceInfo preferenceInfo =
portlet.getInfo().getPreferences().getPreference(key);
+ if (!preferenceInfo.isReadOnly())
+ {
+ String ppValue = (preferenceInfo.getDefaultValue().size() > 0) ?
preferenceInfo.getDefaultValue().get
+ (0) : "";
+ portletPreferenceMaps.put(key, ppValue);
+ }
+ }
+
Portlet pp = uiPortlet.getPreferences();
if (pp != null)
{
- UIFormInputSet uiPortletPrefSet = getChildById(FIELD_PORTLET_PREF);
- uiPortletPrefSet.getChildren().clear();
for (Preference pref : pp)
{
if (!pref.isReadOnly())
{
- UIFormStringInput templateStringInput =
- new UIFormStringInput(pref.getName(), null,
pref.getValues().get(0));
-
templateStringInput.setLabel(res.getString("UIPortletForm.tab.label.Template"));
- templateStringInput.addValidator(MandatoryValidator.class);
- uiPortletPrefSet.addUIFormInput(templateStringInput);
+ portletPreferenceMaps.put(pref.getName(), (pref.getValues().size() >
0) ? pref.getValues().get(0) :
+ "");
}
-
}
- if (uiPortletPrefSet.getChildren().size() > 0)
+ }
+
+ if (portletPreferenceMaps.size() > 0)
+ {
+ Set<String> ppKeySet = portletPreferenceMaps.keySet();
+ UIFormInputSet uiPortletPrefSet = getChildById(FIELD_PORTLET_PREF);
+ uiPortletPrefSet.getChildren().clear();
+ for (String ppKey : ppKeySet)
{
- uiPortletPrefSet.setRendered(true);
- setSelectedTab(FIELD_PORTLET_PREF);
- return;
+ String ppValue = portletPreferenceMaps.get(ppKey);
+ UIFormStringInput preferenceStringInput = new UIFormStringInput(ppKey,
null, ppValue);
+ preferenceStringInput.setLabel(ppKey);
+ preferenceStringInput.addValidator(MandatoryValidator.class);
+ uiPortletPrefSet.addUIFormInput(preferenceStringInput);
}
+
+ uiPortletPrefSet.setRendered(true);
+ setSelectedTab(FIELD_PORTLET_PREF);
+ return;
}
+
setSelectedTab("PortletSetting");
}
}
@@ -336,12 +337,6 @@
return;
}
- //
- PortletInvoker portletInvoker = getApplicationComponent(PortletInvoker.class);
- PortletContext portletContext = uiPortlet_.getPortletContext();
-
- //
-
PropertyChange[] propertyChanges = new PropertyChange[uiFormInputs.size()];
for (int i = 0; i < uiFormInputs.size(); i++)
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/PageNavigationUtils.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/PageNavigationUtils.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/PageNavigationUtils.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -414,7 +414,7 @@
if (nav.getOwnerType().equals(PortalConfig.USER_TYPE))
return;
ResourceBundle res =
- i18nManager.getNavigationResourceBundle(locale.getLanguage(),
nav.getOwnerType(), nav.getOwnerId());
+ i18nManager.getNavigationResourceBundle(locale.toString(), nav.getOwnerType(),
nav.getOwnerId());
for (PageNode node : nav.getNodes())
{
resolveLabel(res, node);
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UINavigationNodeSelector.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UINavigationNodeSelector.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UINavigationNodeSelector.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -150,8 +150,9 @@
*/
public void initTreeData() throws Exception
{
- WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
- localizeNavigation(requestContext.getLocale());
+// Move this to processRender method because of GTNPORTAL-1739
+// WebuiRequestContext requestContext = WebuiRequestContext.getCurrentInstance();
+// localizeNavigation(requestContext.getLocale());
initEdittedTreeNodeData();
}
@@ -294,6 +295,8 @@
public void processRender(WebuiRequestContext context) throws Exception
{
+ localizeNavigation(context.getLocale());
+
UIRightClickPopupMenu uiPopupMenu = getChild(UIRightClickPopupMenu.class);
if (uiPopupMenu != null)
{
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/portal/UILanguageSelector.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/portal/UILanguageSelector.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/portal/UILanguageSelector.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -21,12 +21,16 @@
import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.portal.Constants;
import org.exoplatform.portal.application.PortalRequestContext;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.portal.webui.workspace.UIMaskWorkspace;
import org.exoplatform.portal.webui.workspace.UIPortalApplication;
+import org.exoplatform.services.organization.OrganizationService;
+import org.exoplatform.services.organization.UserProfile;
import org.exoplatform.services.resources.LocaleConfig;
import org.exoplatform.services.resources.LocaleConfigService;
+import org.exoplatform.services.resources.LocaleContextInfo;
import org.exoplatform.services.resources.ResourceBundleService;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
@@ -163,24 +167,54 @@
public void execute(Event<UILanguageSelector> event) throws Exception
{
String language =
event.getRequestContext().getRequestParameter("language");
+ PortalRequestContext prqCtx = PortalRequestContext.getCurrentInstance();
UIPortalApplication uiApp = Util.getUIPortalApplication();
UIMaskWorkspace uiMaskWS =
uiApp.getChildById(UIPortalApplication.UI_MASK_WS_ID);
uiMaskWS.setUIComponent(null);
// event.getRequestContext().addUIComponentToUpdateByAjax(uiMaskWS) ;
- Util.getPortalRequestContext().ignoreAJAXUpdateOnPortlets(false);
- if (language == null || language.trim().length() < 1)
+ prqCtx.ignoreAJAXUpdateOnPortlets(false);
+
+ if (language == null ||
language.trim().equals(prqCtx.getLocale().getLanguage()))
+ {
+ //LocalizationLifecycle will save userProfile if locale is changed
+ //We need to handle case : locale is not changed, but user's locale
setting has not been initialized
+ if (prqCtx.getRemoteUser() != null)
+ {
+ saveLocaleToUserProfile(prqCtx);
+ }
return;
+ }
// if(!uiPortal.isModifiable()) return;
LocaleConfigService localeConfigService =
event.getSource().getApplicationComponent(LocaleConfigService.class);
LocaleConfig localeConfig = localeConfigService.getLocaleConfig(language);
if (localeConfig == null)
localeConfig = localeConfigService.getDefaultLocaleConfig();
- PortalRequestContext prqCtx = PortalRequestContext.getCurrentInstance();
prqCtx.setLocale(localeConfig.getLocale());
//uiApp.setOrientation(localeConfig.getOrientation());
//uiApp.localizeNavigations();
}
+
+ private void saveLocaleToUserProfile(PortalRequestContext context) throws
Exception
+ {
+ ExoContainer container =
context.getApplication().getApplicationServiceContainer();
+ OrganizationService svc = (OrganizationService)
+ container.getComponentInstanceOfType(OrganizationService.class);
+
+ // Don't rely on UserProfileLifecycle loaded UserProfile when doing
+ // an update to avoid a potential overwrite of other changes
+ UserProfile userProfile =
svc.getUserProfileHandler().findUserProfileByName(context.getRemoteUser());
+ if (userProfile != null && userProfile.getUserInfoMap() != null)
+ {
+ //Only save if user's locale has not been set
+ String currLocale =
userProfile.getUserInfoMap().get(Constants.USER_LANGUAGE);
+ if (currLocale == null || currLocale.trim().equals(""))
+ {
+ userProfile.getUserInfoMap().put(Constants.USER_LANGUAGE,
LocaleContextInfo.getLocaleAsString(context.getLocale()));
+ svc.getUserProfileHandler().saveUserProfile(userProfile, false);
+ }
+ }
+ }
}
private String capitalizeFirstLetter(String word)
Modified:
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/portal/UIPortal.java
===================================================================
---
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/portal/UIPortal.java 2011-01-26
11:48:32 UTC (rev 5820)
+++
portal/trunk/webui/portal/src/main/java/org/exoplatform/portal/webui/portal/UIPortal.java 2011-01-27
03:56:42 UTC (rev 5821)
@@ -382,7 +382,7 @@
ResourceBundleManager mgr = getApplicationComponent(ResourceBundleManager.class);
if (nav.getOwnerType().equals(PortalConfig.USER_TYPE))
return;
- ResourceBundle res = mgr.getNavigationResourceBundle(locale.getLanguage(),
nav.getOwnerType(), nav.getOwnerId());
+ ResourceBundle res = mgr.getNavigationResourceBundle(locale.toString(),
nav.getOwnerType(), nav.getOwnerId());
for (PageNode node : nav.getNodes())
{
resolveLabel(res, node);