From fd3826abf42f69db546eff18d269e462843feb49 Mon Sep 17 00:00:00 2001
From: Leif Åstrand
null
if no resource is registered for the key
- *
- * @since 7.0
- */
- public ApplicationResource getResource(String key) {
- return keyResourceMap.get(key);
- }
-
/**
* Thread local for keeping track of currently used application instance
*
@@ -2510,4 +2428,30 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
return true;
}
+
+ /**
+ * Gets this application's global resource handler that takes care of
+ * serving connector resources that are not served by any single connector
+ * because e.g. because they are served with strong caching or because of
+ * legacy reasons.
+ *
+ * @param createOnDemand
+ * true
if a resource handler should be initialized
+ * if there is no handler associated with this application.
+ * false if null should be returned
+ * if there is no registered handler.
+ * @return this application's global resource handler, or null
+ * if there is no handler and the createOnDemand parameter is
+ * false
.
+ *
+ * @since 7.0.0
+ */
+ public GlobalResourceHandler getGlobalResourceHandler(boolean createOnDemand) {
+ if (globalResourceHandler == null && createOnDemand) {
+ globalResourceHandler = new GlobalResourceHandler();
+ addRequestHandler(globalResourceHandler);
+ }
+
+ return globalResourceHandler;
+ }
}
diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java
index 745ccf679c..fa127fa2aa 100644
--- a/server/src/com/vaadin/server/AbstractClientConnector.java
+++ b/server/src/com/vaadin/server/AbstractClientConnector.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.server;
+import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
@@ -367,8 +368,8 @@ public abstract class AbstractClientConnector implements ClientConnector {
/**
* Finds a UI ancestor of this connector. null
is returned if
- * no UI ancestor is found (typically because the connector is not
- * attached to a proper hierarchy).
+ * no UI ancestor is found (typically because the connector is not attached
+ * to a proper hierarchy).
*
* @return the UI ancestor of this connector, or null
if none
* is found.
@@ -561,4 +562,59 @@ public abstract class AbstractClientConnector implements ClientConnector {
public void beforeClientResponse(boolean initial) {
// Do nothing by default
}
+
+ @Override
+ public boolean handleConnectorRequest(WrappedRequest request,
+ WrappedResponse response, String path) throws IOException {
+ String[] parts = path.split("/", 2);
+ String key = parts[0];
+
+ ConnectorResource resource = (ConnectorResource) getResource(key);
+ if (resource != null) {
+ DownloadStream stream = resource.getStream();
+ stream.writeTo(response);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Gets a resource defined using {@link #setResource(String, Resource)} with
+ * the corresponding key.
+ *
+ * @param key
+ * the string identifier of the resource
+ * @return a resource, or null
if there's no resource
+ * associated with the given key
+ *
+ * @see #setResource(String, Resource)
+ */
+ protected Resource getResource(String key) {
+ return ResourceReference.getResource(getState().resources.get(key));
+ }
+
+ /**
+ * Registers a resource with this connector using the given key. This will
+ * make the URL for retrieving the resource available to the client-side
+ * connector using
+ * {@link com.vaadin.terminal.gwt.client.ui.AbstractConnector#getResourceUrl(String)}
+ * with the same key.
+ *
+ * @param key
+ * the string key to associate the resource with
+ * @param resource
+ * the resource to set, or null
to clear a previous
+ * association.
+ */
+ protected void setResource(String key, Resource resource) {
+ ResourceReference resourceReference = ResourceReference.create(
+ resource, this, key);
+
+ if (resourceReference == null) {
+ getState().resources.remove(key);
+ } else {
+ getState().resources.put(key, resourceReference);
+ }
+ }
}
diff --git a/server/src/com/vaadin/server/AbstractCommunicationManager.java b/server/src/com/vaadin/server/AbstractCommunicationManager.java
index 2d60c6e587..2655ee9a00 100644
--- a/server/src/com/vaadin/server/AbstractCommunicationManager.java
+++ b/server/src/com/vaadin/server/AbstractCommunicationManager.java
@@ -103,10 +103,10 @@ public abstract class AbstractCommunicationManager implements Serializable {
private static final String DASHDASH = "--";
- private static final RequestHandler APP_RESOURCE_HANDLER = new ApplicationResourceHandler();
-
private static final RequestHandler UNSUPPORTED_BROWSER_HANDLER = new UnsupportedBrowserHandler();
+ private static final RequestHandler CONNECTOR_RESOURCE_HANDLER = new ConnectorResourceHandler();
+
/**
* TODO Document me!
*
@@ -178,8 +178,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
public AbstractCommunicationManager(Application application) {
this.application = application;
application.addRequestHandler(getBootstrapHandler());
- application.addRequestHandler(APP_RESOURCE_HANDLER);
application.addRequestHandler(UNSUPPORTED_BROWSER_HANDLER);
+ application.addRequestHandler(CONNECTOR_RESOURCE_HANDLER);
requireLocale(application.getLocale().toString());
}
diff --git a/server/src/com/vaadin/server/AbstractWebApplicationContext.java b/server/src/com/vaadin/server/AbstractWebApplicationContext.java
index 78cf8fdab8..cf983f4c80 100644
--- a/server/src/com/vaadin/server/AbstractWebApplicationContext.java
+++ b/server/src/com/vaadin/server/AbstractWebApplicationContext.java
@@ -18,9 +18,6 @@ package com.vaadin.server;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -35,7 +32,6 @@ import javax.servlet.http.HttpSessionBindingListener;
import com.vaadin.Application;
import com.vaadin.service.ApplicationContext;
-import com.vaadin.shared.ApplicationConstants;
/**
* Base class for web application contexts (including portlet contexts) that
@@ -186,66 +182,6 @@ public abstract class AbstractWebApplicationContext implements
applicationToAjaxAppMgrMap.remove(application);
}
- @Override
- public String generateApplicationResourceURL(ApplicationResource resource,
- String mapKey) {
-
- final String filename = resource.getFilename();
- if (filename == null) {
- return ApplicationConstants.APP_PROTOCOL_PREFIX
- + ApplicationConstants.APP_REQUEST_PATH + mapKey + "/";
- } else {
- // #7738 At least Tomcat and JBoss refuses requests containing
- // encoded slashes or backslashes in URLs. Application resource URLs
- // should really be passed in another way than as part of the path
- // in the future.
- String encodedFileName = urlEncode(filename).replace("%2F", "/")
- .replace("%5C", "\\");
- return ApplicationConstants.APP_PROTOCOL_PREFIX
- + ApplicationConstants.APP_REQUEST_PATH + mapKey + "/"
- + encodedFileName;
- }
-
- }
-
- static String urlEncode(String filename) {
- try {
- return URLEncoder.encode(filename, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(
- "UTF-8 charset not available (\"this should never happen\")",
- e);
- }
- }
-
- @Override
- public boolean isApplicationResourceURL(URL context, String relativeUri) {
- // If the relative uri is null, we are ready
- if (relativeUri == null) {
- return false;
- }
-
- // Resolves the prefix
- String prefix = relativeUri;
- final int index = relativeUri.indexOf('/');
- if (index >= 0) {
- prefix = relativeUri.substring(0, index);
- }
-
- // Handles the resource requests
- return (prefix.equals("APP"));
- }
-
- @Override
- public String getURLKey(URL context, String relativeUri) {
- final int index = relativeUri.indexOf('/');
- final int next = relativeUri.indexOf('/', index + 1);
- if (next < 0) {
- return null;
- }
- return relativeUri.substring(index + 1, next);
- }
-
/**
* @return The total time spent servicing requests in this session.
*/
diff --git a/server/src/com/vaadin/server/ApplicationResource.java b/server/src/com/vaadin/server/ApplicationResource.java
deleted file mode 100644
index b18886ed55..0000000000
--- a/server/src/com/vaadin/server/ApplicationResource.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2011 Vaadin Ltd.
- *
- * Licensed 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.
- */
-
-package com.vaadin.server;
-
-import java.io.Serializable;
-
-import com.vaadin.Application;
-
-/**
- * This interface must be implemented by classes wishing to provide Application
- * resources.
- *
- * ApplicationResource
are a set of named resources (pictures,
- * sounds, etc) associated with some specific application. Having named
- * application resources provides a convenient method for having inter-theme
- * common resources for an application.
- *
- * This gives the adapter the possibility cache streams sent to the client.
- * The caching may be made in adapter or at the client if the client
- * supports caching. Default is DEFAULT_CACHETIME
.
- *
- * If the buffer size is 0, the buffer size is decided by the terminal - * adapter. The default value is 0. - *
- * - * @return int the size of the buffer in bytes. - */ - public int getBufferSize(); - -} diff --git a/server/src/com/vaadin/server/ApplicationResourceHandler.java b/server/src/com/vaadin/server/ApplicationResourceHandler.java deleted file mode 100644 index 1cad5efcfd..0000000000 --- a/server/src/com/vaadin/server/ApplicationResourceHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed 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. - */ - -package com.vaadin.server; - -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.http.HttpServletResponse; - -import com.vaadin.Application; - -public class ApplicationResourceHandler implements RequestHandler { - private static final Pattern APP_RESOURCE_PATTERN = Pattern - .compile("^/?APP/(\\d+)/.*"); - - @Override - public boolean handleRequest(Application application, - WrappedRequest request, WrappedResponse response) - throws IOException { - // Check for application resources - String requestPath = request.getRequestPathInfo(); - if (requestPath == null) { - return false; - } - Matcher resourceMatcher = APP_RESOURCE_PATTERN.matcher(requestPath); - - if (resourceMatcher.matches()) { - ApplicationResource resource = application - .getResource(resourceMatcher.group(1)); - if (resource != null) { - DownloadStream stream = resource.getStream(); - if (stream != null) { - stream.setCacheTime(resource.getCacheTime()); - stream.writeTo(response); - return true; - } - } - // We get here if the url looks like an application resource but no - // resource can be served - response.sendError(HttpServletResponse.SC_NOT_FOUND, - request.getRequestPathInfo() + " can not be found"); - return true; - } - - return false; - } -} diff --git a/server/src/com/vaadin/server/ClassResource.java b/server/src/com/vaadin/server/ClassResource.java index 4b4837faa3..2f05115fd4 100644 --- a/server/src/com/vaadin/server/ClassResource.java +++ b/server/src/com/vaadin/server/ClassResource.java @@ -20,6 +20,8 @@ import java.io.Serializable; import com.vaadin.Application; import com.vaadin.service.FileTypeResolver; +import com.vaadin.ui.UI; +import com.vaadin.ui.UI.LegacyWindow; /** *ClassResource
is a named resource accessed with the class
@@ -33,7 +35,7 @@ import com.vaadin.service.FileTypeResolver;
* @since 3.0
*/
@SuppressWarnings("serial")
-public class ClassResource implements ApplicationResource, Serializable {
+public class ClassResource implements ConnectorResource, Serializable {
/**
* Default buffer size for this stream resource.
@@ -43,10 +45,10 @@ public class ClassResource implements ApplicationResource, Serializable {
/**
* Default cache time for this stream resource.
*/
- private long cacheTime = DEFAULT_CACHETIME;
+ private long cacheTime = DownloadStream.DEFAULT_CACHETIME;
/**
- * Associated class used for indetifying the source of the resource.
+ * Associated class used for identifying the source of the resource.
*/
private final Class> associatedClass;
@@ -55,22 +57,16 @@ public class ClassResource implements ApplicationResource, Serializable {
*/
private final String resourceName;
- /**
- * Application used for serving the class.
- */
- private final Application application;
-
/**
* Creates a new application resource instance. The resource id is relative
- * to the location of the application class.
+ * to the location of the UI of the component using this resource (or the
+ * Application if using LegacyWindow).
*
* @param resourceName
* the Unique identifier of the resource within the application.
- * @param application
- * the application this resource will be added to.
*/
- public ClassResource(String resourceName, Application application) {
- this(application.getClass(), resourceName, application);
+ public ClassResource(String resourceName) {
+ this(null, resourceName);
}
/**
@@ -80,18 +76,13 @@ public class ClassResource implements ApplicationResource, Serializable {
* the class of the which the resource is associated.
* @param resourceName
* the Unique identifier of the resource within the application.
- * @param application
- * the application this resource will be added to.
*/
- public ClassResource(Class> associatedClass, String resourceName,
- Application application) {
+ public ClassResource(Class> associatedClass, String resourceName) {
this.associatedClass = associatedClass;
this.resourceName = resourceName;
- this.application = application;
- if (resourceName == null || associatedClass == null) {
+ if (resourceName == null) {
throw new NullPointerException();
}
- application.addResource(this);
}
/**
@@ -104,50 +95,43 @@ public class ClassResource implements ApplicationResource, Serializable {
return FileTypeResolver.getMIMEType(resourceName);
}
- /**
- * Gets the application of this resource.
- *
- * @see com.vaadin.server.ApplicationResource#getApplication()
- */
- @Override
- public Application getApplication() {
- return application;
- }
-
- /**
- * Gets the virtual filename for this resource.
- *
- * @return the file name associated to this resource.
- * @see com.vaadin.server.ApplicationResource#getFilename()
- */
@Override
public String getFilename() {
- int index = 0;
- int next = 0;
- while ((next = resourceName.indexOf('/', index)) > 0
- && next + 1 < resourceName.length()) {
- index = next + 1;
- }
- return resourceName.substring(index);
+ String[] parts = resourceName.split("/");
+ return parts[parts.length - 1];
}
- /**
- * Gets resource as stream.
- *
- * @see com.vaadin.server.ApplicationResource#getStream()
- */
@Override
public DownloadStream getStream() {
- final DownloadStream ds = new DownloadStream(
- associatedClass.getResourceAsStream(resourceName),
- getMIMEType(), getFilename());
+ final DownloadStream ds = new DownloadStream(getAssociatedClass()
+ .getResourceAsStream(resourceName), getMIMEType(),
+ getFilename());
ds.setBufferSize(getBufferSize());
- ds.setCacheTime(cacheTime);
+ ds.setCacheTime(getCacheTime());
return ds;
}
- /* documented in superclass */
- @Override
+ protected Class> getAssociatedClass() {
+ if (associatedClass == null) {
+ Class extends UI> associatedClass = UI.getCurrent().getClass();
+ if (associatedClass == LegacyWindow.class) {
+ return Application.getCurrent().getClass();
+ }
+ return associatedClass;
+ }
+ return associatedClass;
+ }
+
+ /**
+ * Gets the size of the download buffer used for this resource.
+ *
+ * + * If the buffer size is 0, the buffer size is decided by the terminal + * adapter. The default value is 0. + *
+ * + * @return the size of the buffer in bytes. + */ public int getBufferSize() { return bufferSize; } @@ -157,13 +141,24 @@ public class ClassResource implements ApplicationResource, Serializable { * * @param bufferSize * the size of the buffer in bytes. + * + * @see #getBufferSize() */ public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } - /* documented in superclass */ - @Override + /** + * Gets the length of cache expiration time. + * + *+ * This gives the adapter the possibility cache streams sent to the client. + * The caching may be made in adapter or at the client if the client + * supports caching. Default is {@link DownloadStream#DEFAULT_CACHETIME}. + *
+ * + * @return Cache time in milliseconds + */ public long getCacheTime() { return cacheTime; } @@ -174,7 +169,7 @@ public class ClassResource implements ApplicationResource, Serializable { ** This gives the adapter the possibility cache streams sent to the client. * The caching may be made in adapter or at the client if the client - * supports caching. Zero or negavive value disbales the caching of this + * supports caching. Zero or negative value disables the caching of this * stream. *
* diff --git a/server/src/com/vaadin/server/ClientConnector.java b/server/src/com/vaadin/server/ClientConnector.java index ce392ce226..3a340c2d7d 100644 --- a/server/src/com/vaadin/server/ClientConnector.java +++ b/server/src/com/vaadin/server/ClientConnector.java @@ -15,6 +15,7 @@ */ package com.vaadin.server; +import java.io.IOException; import java.util.Collection; import java.util.List; @@ -211,4 +212,30 @@ public interface ClientConnector extends Connector, RpcTarget { * if the state can not be encoded */ public JSONObject encodeState() throws JSONException; + + /** + * Handle a request directed to this connector. This can be used by + * connectors to dynamically generate a response and it is also used + * internally when serving {@link ConnectorResource}s. + *
+ * Requests to /APP/connector/[ui id]/[connector id]/
are
+ * routed to this method with the remaining part of the requested path
+ * available in the path parameter.
+ *
+ * {@link DynamicConnectorResource} can be used to easily make an
+ * appropriate URL available to the client-side code.
+ *
+ * @param request
+ * the request that should be handled
+ * @param response
+ * the response object to which the response should be written
+ * @param path
+ * the requested relative path
+ * @return
+ * If the buffer size is 0, the buffer size is decided by the terminal
+ * adapter. The default value is 0.
+ *
+ * A {@link ConnectorResource} registered for a {@link Vaadin6Component}
+ * will be set to be served with a global URL. Other resource types will be
+ * ignored and thus not served by this handler.
+ *
+ * @param resource
+ * the resource to register
+ * @param ownerConnector
+ * the connector to which the resource belongs
+ */
+ public void register(Resource resource, ClientConnector ownerConnector) {
+ if (resource instanceof ConnectorResource) {
+ if (!(ownerConnector instanceof LegacyComponent)) {
+ throw new IllegalArgumentException(
+ "A normal ConnectorResource can only be registered for legacy components.");
+ }
+ ConnectorResource connectorResource = (ConnectorResource) resource;
+ if (!legacyResourceKeys.containsKey(resource)) {
+ String uri = LEGACY_TYPE + '/'
+ + Integer.toString(nextLegacyId++);
+ String filename = connectorResource.getFilename();
+ if (filename != null && !filename.isEmpty()) {
+ uri += '/' + filename;
+ }
+ legacyResourceKeys.put(connectorResource, uri);
+ legacyResources.put(uri, connectorResource);
+ registerResourceUsage(connectorResource, ownerConnector);
+ }
+ }
+ }
+
+ private void unregisterResource(Resource resource) {
+ String oldUri = legacyResourceKeys.remove(resource);
+ if (oldUri != null) {
+ legacyResources.remove(oldUri);
+ }
+ }
+
+ private void registerResourceUsage(Resource resource,
+ ClientConnector connector) {
+ ensureInSet(resourceUsers, resource, connector);
+ ensureInSet(usedResources, connector, resource);
+ }
+
+ private
+ * If the buffer size is 0, the buffer size is decided by the terminal
+ * adapter. The default value is 0.
+ * true
if the request has been handled,
+ * false
if no response has been written.
+ * @throws IOException
+ * if there is a problem generating a response.
+ */
+ public boolean handleConnectorRequest(WrappedRequest request,
+ WrappedResponse response, String path) throws IOException;
}
diff --git a/server/src/com/vaadin/server/ConnectorResource.java b/server/src/com/vaadin/server/ConnectorResource.java
new file mode 100644
index 0000000000..7f30de4bbe
--- /dev/null
+++ b/server/src/com/vaadin/server/ConnectorResource.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed 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.
+ */
+
+package com.vaadin.server;
+
+
+/**
+ * A resource that is served through the Connector that is using the resource.
+ *
+ * @see AbstractClientConnector#setResource(String, Resource)
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public interface ConnectorResource extends Resource {
+ public static final String CONNECTOR_REQUEST_PATH = "connector/";
+
+ /**
+ * Gets resource as stream.
+ */
+ public DownloadStream getStream();
+
+ /**
+ * Gets the virtual filename for this resource.
+ *
+ * @return the file name associated to this resource.
+ */
+ public String getFilename();
+}
diff --git a/server/src/com/vaadin/server/ConnectorResourceHandler.java b/server/src/com/vaadin/server/ConnectorResourceHandler.java
new file mode 100644
index 0000000000..b988510b8e
--- /dev/null
+++ b/server/src/com/vaadin/server/ConnectorResourceHandler.java
@@ -0,0 +1,81 @@
+package com.vaadin.server;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletResponse;
+
+import com.vaadin.Application;
+import com.vaadin.shared.ApplicationConstants;
+import com.vaadin.ui.UI;
+
+public class ConnectorResourceHandler implements RequestHandler {
+ // APP/connector/[uiid]/[cid]/[filename.xyz]
+ private static final Pattern CONNECTOR_RESOURCE_PATTERN = Pattern
+ .compile("^/?" + ApplicationConstants.APP_REQUEST_PATH
+ + ConnectorResource.CONNECTOR_REQUEST_PATH
+ + "(\\d+)/(\\d+)/(.*)");
+
+ private static Logger getLogger() {
+ return Logger.getLogger(ConnectorResourceHandler.class.getName());
+
+ }
+
+ @Override
+ public boolean handleRequest(Application application,
+ WrappedRequest request, WrappedResponse response)
+ throws IOException {
+ String requestPath = request.getRequestPathInfo();
+ if (requestPath == null) {
+ return false;
+ }
+ Matcher matcher = CONNECTOR_RESOURCE_PATTERN.matcher(requestPath);
+ if (matcher.matches()) {
+ String uiId = matcher.group(1);
+ String cid = matcher.group(2);
+ String key = matcher.group(3);
+ UI ui = application.getUIById(Integer.parseInt(uiId));
+ if (ui == null) {
+ return error(request, response,
+ "Ignoring connector request for no-existent root "
+ + uiId);
+ }
+
+ UI.setCurrent(ui);
+ Application.setCurrent(ui.getApplication());
+
+ ClientConnector connector = ui.getConnectorTracker().getConnector(
+ cid);
+ if (connector == null) {
+ return error(request, response,
+ "Ignoring connector request for no-existent connector "
+ + cid + " in root " + uiId);
+ }
+
+ if (!connector.handleConnectorRequest(request, response, key)) {
+ return error(request, response, connector.getClass()
+ .getSimpleName()
+ + " ("
+ + connector.getConnectorId()
+ + ") did not handle connector request for " + key);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private static boolean error(WrappedRequest request,
+ WrappedResponse response, String logMessage) throws IOException {
+ getLogger().log(Level.WARNING, logMessage);
+ response.sendError(HttpServletResponse.SC_NOT_FOUND,
+ request.getRequestPathInfo() + " can not be found");
+
+ // Request handled (though not in a nice way)
+ return true;
+ }
+}
diff --git a/server/src/com/vaadin/server/DragAndDropService.java b/server/src/com/vaadin/server/DragAndDropService.java
index 29825496b5..3e7de5c9a2 100644
--- a/server/src/com/vaadin/server/DragAndDropService.java
+++ b/server/src/com/vaadin/server/DragAndDropService.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.server;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
@@ -338,4 +339,10 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public boolean handleConnectorRequest(WrappedRequest request,
+ WrappedResponse response, String path) throws IOException {
+ return false;
+ }
}
diff --git a/server/src/com/vaadin/server/DynamicConnectorResource.java b/server/src/com/vaadin/server/DynamicConnectorResource.java
new file mode 100644
index 0000000000..8269f261f7
--- /dev/null
+++ b/server/src/com/vaadin/server/DynamicConnectorResource.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed 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.
+ */
+
+package com.vaadin.server;
+
+import java.util.Collections;
+import java.util.Map;
+
+import com.vaadin.service.FileTypeResolver;
+
+/**
+ * A resource that is served by calling
+ * {@link ClientConnector#handleConnectorRequest(WrappedRequest, WrappedResponse, String)}
+ * with appropriate parameters.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class DynamicConnectorResource implements Resource {
+
+ private final ClientConnector connector;
+ private final String path;
+ private final Mapnull
if the resource is not
+ * registered.
+ */
+ public String getUri(ClientConnector connector, ConnectorResource resource) {
+ // app://APP/global/[ui]/[type]/[id]
+ String uri = legacyResourceKeys.get(resource);
+ if (uri != null && !uri.isEmpty()) {
+ return ApplicationConstants.APP_PROTOCOL_PREFIX
+ + ApplicationConstants.APP_REQUEST_PATH
+ + RESOURCE_REQUEST_PATH + connector.getUI().getUIId() + '/'
+ + uri;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Notifies this handler that resources registered for the given connector
+ * can be released.
+ *
+ * @param connector
+ * the connector for which any registered resources can be
+ * released.
+ */
+ public void unregisterConnector(ClientConnector connector) {
+ SetDownloadStream.DEFAULT_CACHETIME
.
+ *
+ * @return Cache time in milliseconds.
+ */
public long getCacheTime() {
return cacheTime;
}
@@ -227,4 +217,29 @@ public class StreamResource implements ApplicationResource {
this.cacheTime = cacheTime;
}
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (obj instanceof StreamResource) {
+ StreamResource that = (StreamResource) obj;
+ return getStreamSource().equals(that.getStreamSource())
+ && getMIMEType().equals(that.getMIMEType())
+ && String.valueOf(getFilename()).equals(
+ String.valueOf(that.getFilename()))
+ && getBufferSize() == that.getBufferSize()
+ && getCacheTime() == that.getCacheTime();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (getStreamSource().hashCode() + 37
+ * getMIMEType().hashCode() + 37 ^ 2
+ * String.valueOf(getFilename()).hashCode() + 37 ^ 3
+ * getBufferSize() + 37 ^ 4 * getCacheTime());
+ }
+
}
diff --git a/server/src/com/vaadin/service/ApplicationContext.java b/server/src/com/vaadin/service/ApplicationContext.java
index 08e553d0e5..591704764f 100644
--- a/server/src/com/vaadin/service/ApplicationContext.java
+++ b/server/src/com/vaadin/service/ApplicationContext.java
@@ -18,12 +18,9 @@ package com.vaadin.service;
import java.io.File;
import java.io.Serializable;
-import java.net.URL;
import java.util.Collection;
import com.vaadin.Application;
-import com.vaadin.server.AbstractCommunicationManager;
-import com.vaadin.server.ApplicationResource;
/**
* ApplicationContext
provides information about the running
@@ -85,59 +82,6 @@ public interface ApplicationContext extends Serializable {
*/
public int getMaxInactiveInterval();
- /**
- * Generate a URL that can be used as the relative location of e.g. an
- * {@link ApplicationResource}.
- *
- * This method should only be called from the processing of a UIDL request,
- * not from a background thread. The return value is null if used outside a
- * suitable request.
- *
- * @deprecated this method is intended for terminal implementation only and
- * is subject to change/removal from the interface (to
- * {@link AbstractCommunicationManager})
- *
- * @param resource
- * @param urlKey
- * a key for the resource that can later be extracted from a URL
- * with {@link #getURLKey(URL, String)}
- */
- @Deprecated
- public String generateApplicationResourceURL(ApplicationResource resource,
- String urlKey);
-
- /**
- * Tests if a URL is for an application resource (APP/...).
- *
- * @deprecated this method is intended for terminal implementation only and
- * is subject to change/removal from the interface (to
- * {@link AbstractCommunicationManager})
- *
- * @param context
- * @param relativeUri
- * @return
- */
- @Deprecated
- public boolean isApplicationResourceURL(URL context, String relativeUri);
-
- /**
- * Gets the identifier (key) from an application resource URL. This key is
- * the one that was given to
- * {@link #generateApplicationResourceURL(ApplicationResource, String)} when
- * creating the URL.
- *
- * @deprecated this method is intended for terminal implementation only and
- * is subject to change/removal from the interface (to
- * {@link AbstractCommunicationManager})
- *
- *
- * @param context
- * @param relativeUri
- * @return
- */
- @Deprecated
- public String getURLKey(URL context, String relativeUri);
-
/**
* Interface for listening to transaction events. Implement this interface
* to listen to all transactions between the client and the application.
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index 47d893cd27..045173036e 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -37,8 +37,8 @@ import com.vaadin.server.ClientConnector;
import com.vaadin.server.ComponentSizeValidator;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.Resource;
-import com.vaadin.server.ResourceReference;
import com.vaadin.server.Terminal;
+import com.vaadin.shared.ComponentConstants;
import com.vaadin.shared.ComponentState;
import com.vaadin.tools.ReflectTools;
@@ -297,7 +297,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
*/
@Override
public Resource getIcon() {
- return ResourceReference.getResource(getState().getIcon());
+ return getResource(ComponentConstants.ICON_RESOURCE);
}
/**
@@ -309,7 +309,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
*/
@Override
public void setIcon(Resource icon) {
- getState().setIcon(ResourceReference.create(icon));
+ setResource(ComponentConstants.ICON_RESOURCE, icon);
}
/*
diff --git a/server/src/com/vaadin/ui/AbstractEmbedded.java b/server/src/com/vaadin/ui/AbstractEmbedded.java
index f3256dcde6..d94f62120f 100644
--- a/server/src/com/vaadin/ui/AbstractEmbedded.java
+++ b/server/src/com/vaadin/ui/AbstractEmbedded.java
@@ -5,7 +5,6 @@
package com.vaadin.ui;
import com.vaadin.server.Resource;
-import com.vaadin.server.ResourceReference;
import com.vaadin.shared.ui.AbstractEmbeddedState;
/**
@@ -32,12 +31,7 @@ public abstract class AbstractEmbedded extends AbstractComponent {
* the source to set.
*/
public void setSource(Resource source) {
- if (source == null) {
- getState().setSource(null);
- } else {
- getState().setSource(new ResourceReference(source));
- }
- requestRepaint();
+ setResource(AbstractEmbeddedState.SOURCE_RESOURCE, source);
}
/**
@@ -46,12 +40,7 @@ public abstract class AbstractEmbedded extends AbstractComponent {
* @return the source
*/
public Resource getSource() {
- ResourceReference ref = ((ResourceReference) getState().getSource());
- if (ref == null) {
- return null;
- } else {
- return ref.getResource();
- }
+ return getResource(AbstractEmbeddedState.SOURCE_RESOURCE);
}
/**
diff --git a/server/src/com/vaadin/ui/AbstractMedia.java b/server/src/com/vaadin/ui/AbstractMedia.java
index f9eb67f666..940d85a8b9 100644
--- a/server/src/com/vaadin/ui/AbstractMedia.java
+++ b/server/src/com/vaadin/ui/AbstractMedia.java
@@ -16,11 +16,18 @@
package com.vaadin.ui;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import com.vaadin.server.ConnectorResource;
import com.vaadin.server.Resource;
import com.vaadin.server.ResourceReference;
+import com.vaadin.server.WrappedRequest;
+import com.vaadin.server.WrappedResponse;
import com.vaadin.shared.communication.URLReference;
import com.vaadin.shared.ui.AbstractMediaState;
import com.vaadin.shared.ui.MediaControl;
@@ -64,11 +71,43 @@ public abstract class AbstractMedia extends AbstractComponent {
*/
public void addSource(Resource source) {
if (source != null) {
- getState().getSources().add(new ResourceReference(source));
+ List