浏览代码

Add pluggable connector id generator support

tags/8.1.0.beta2
Leif Åstrand 7 年前
父节点
当前提交
f8f8cc0385

+ 75
- 0
server/src/main/java/com/vaadin/server/ConnectorIdGenerationEvent.java 查看文件

@@ -0,0 +1,75 @@
/*
* Copyright 2000-2016 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.EventObject;

import com.vaadin.shared.Connector;

/**
* Event object containing information related to connector id generation.
*
* @author Vaadin Ltd
* @since 8.1
*/
public class ConnectorIdGenerationEvent extends EventObject {

private final VaadinSession session;
private final Connector connector;

/**
* Creates a new event for the given session and connector.
*
* @param session
* the session for which a connector id is needed, not
* <code>null</code>
* @param connector
* the connector that should get an id, not <code>null</code>
*/
public ConnectorIdGenerationEvent(VaadinSession session,
Connector connector) {
super(session.getService());

assert session != null;
assert connector != null;

this.session = session;
this.connector = connector;
}

/**
* Gets the session for which connector id is needed.
*
* @return the session, not <code>null</code>
*/
public VaadinSession getSession() {
return session;
}

/**
* Gets the connector that should get an id.
*
* @return the connector, not <code>null</code>
*/
public Connector getConnector() {
return connector;
}

@Override
public VaadinService getSource() {
return (VaadinService) super.getSource();
}
}

+ 56
- 0
server/src/main/java/com/vaadin/server/ConnectorIdGenerator.java 查看文件

@@ -0,0 +1,56 @@
/*
* Copyright 2000-2016 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;

/**
* Callback for generating the id for new connectors. A generator can be
* registered to be used with an application by overriding
* {@link VaadinService#initConenctorIdGenerator(java.util.List)} or by calling
* {@link ServiceInitEvent#addConnectorIdGenerator(ConnectorIdGenerator)} from a
* {@link VaadinServiceInitListener}.
*
* @author Vaadin Ltd
* @since 8.1
*/
@FunctionalInterface
public interface ConnectorIdGenerator extends Serializable {
/**
* Generates a connector id for a connector.
*
* @param event
* the event object that has a reference to the connector and the
* session, not <code>null</code>
* @return the connector id to use for the connector, not <code>null</code>
*/
public String generateConnectorId(ConnectorIdGenerationEvent event);

/**
* Generates a connector id using the default logic by using
* {@link VaadinSession#getNextConnectorId()}.
*
* @param event
* the event object that has a reference to the connector and the
* session, not <code>null</code>
* @return the connector id to use for the connector, not <code>null</code>
*/
public static String generateDefaultConnectorId(
ConnectorIdGenerationEvent event) {
assert event != null;
return event.getSession().getNextConnectorId();
}
}

+ 36
- 0
server/src/main/java/com/vaadin/server/ServiceInitEvent.java 查看文件

@@ -35,6 +35,7 @@ public class ServiceInitEvent extends EventObject {

private List<RequestHandler> addedRequestHandlers = new ArrayList<>();
private List<DependencyFilter> addedDependencyFilters = new ArrayList<>();
private List<ConnectorIdGenerator> addedConnectorIdGenerators = new ArrayList<>();

/**
* Creates a new service init event for a given {@link VaadinService} and
@@ -99,6 +100,41 @@ public class ServiceInitEvent extends EventObject {
return Collections.unmodifiableList(addedDependencyFilters);
}

/**
* Adds as connector id generator to be used by this service. By default,
* the service will fail to deploy if more than one connector id generator
* has been registered.
*
* @param connectorIdGenerator
* the connector id generator to add, not <code>null</code>
*
* @since 8.1
*/
public void addConnectorIdGenerator(
ConnectorIdGenerator connectorIdGenerator) {
Objects.requireNonNull(connectorIdGenerator,
"Connector id generator cannot be null");

/*
* We're collecting all generators so that a custom service
* implementation can pick which one to use even though the default
* implementation throws if there are more than one.
*/
addedConnectorIdGenerators.add(connectorIdGenerator);
}

/**
* Gets an unmodifiable list of all connector id generators that have been
* added for the service.
*
* @return the current list of added connector id generators
*
* @since 8.1
*/
public List<ConnectorIdGenerator> getAddedConnectorIdGenerators() {
return Collections.unmodifiableList(addedConnectorIdGenerators);
}

@Override
public VaadinService getSource() {
return (VaadinService) super.getSource();

+ 77
- 0
server/src/main/java/com/vaadin/server/VaadinService.java 查看文件

@@ -136,6 +136,7 @@ public abstract class VaadinService implements Serializable {

private Iterable<RequestHandler> requestHandlers;
private Iterable<DependencyFilter> dependencyFilters;
private ConnectorIdGenerator connectorIdGenerator;

private boolean atmosphereAvailable = checkAtmosphereSupport();

@@ -209,6 +210,11 @@ public abstract class VaadinService implements Serializable {

dependencyFilters = Collections.unmodifiableCollection(
initDependencyFilters(event.getAddedDependencyFilters()));

connectorIdGenerator = initConenctorIdGenerator(
event.getAddedConnectorIdGenerators());
assert connectorIdGenerator != null;

initialized = true;
}

@@ -1476,6 +1482,49 @@ public abstract class VaadinService implements Serializable {
return sessionInitFilters;
}

/**
* Determines the connector id generator to use for the application.
* <p>
* The connector id generator creates a unique id for each connector
* attached to a UI.
* <p>
* The framework collects generators from the {@link SessionInitEvent} where
* session init listeners can add them. This method is called with the
* combined list to determine one generator to use.
* <p>
* If the list is empty, a default implementation based on
* {@link VaadinSession#getNextConnectorId()} is used. If the list contains
* one item, it is used. If there are multiple generators in the list, an
* exception is thrown.
*
* @since 8.1
* @param addedConnectorIdGenerators
* a list of connector id generators collected from the session
* init event, not <code>null</code>
* @return the connector id generator to use, not <code>null</code>
*
* @throws ServiceException
* if something went wrong while determining the filters, e.g.
* if there are multiple implementations to choose from
*
*/
protected ConnectorIdGenerator initConenctorIdGenerator(
List<ConnectorIdGenerator> addedConnectorIdGenerators)
throws ServiceException {
assert addedConnectorIdGenerators != null;

switch (addedConnectorIdGenerators.size()) {
case 0:
return ConnectorIdGenerator::generateDefaultConnectorId;
case 1:
return addedConnectorIdGenerators.get(0);
default:
throw new ServiceException(
"Cannot start application since there are multiple connector id generators. Remove redundant implementations from the classpath or override VaadinService.initConenctorIdGenerator to explicitly select one to use. The found generators are: "
+ addedConnectorIdGenerators);
}
}

/**
* Gets the filters which all resource dependencies are passed through
* before being sent to the client for loading.
@@ -2149,4 +2198,32 @@ public abstract class VaadinService implements Serializable {
return VaadinSession.class.getName() + "." + getServiceName();
}

/**
* Generates a unique id to use for a newly attached connector.
*
* @see ConnectorIdGenerator
* @see #initConenctorIdGenerator(List)
*
* @since 8.1
*
* @param session
* the session to which the connector has been attached, not
* <code>null</code>
* @param connector
* the attached connector for which to generate an id, not
* <code>null</code>
* @return a string id that is unique within the session, not
* <code>null</code>
*/
public String generateConnectorId(VaadinSession session,
ClientConnector connector) {
assert session.getService() == this;
String connectorId = connectorIdGenerator.generateConnectorId(
new ConnectorIdGenerationEvent(session, connector));

assert connectorId != null;

return connectorId;
}

}

+ 16
- 2
server/src/main/java/com/vaadin/server/VaadinSession.java 查看文件

@@ -754,11 +754,25 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* A connector that has not yet been assigned an id.
* @return A new id for the connector
*
* @deprecated As of 7.0. Will likely change or be removed in a future
* version
* @deprecated As of 7.0. Use
* {@link VaadinService#generateConnectorId(VaadinSession, ClientConnector)}
* instead.
*/
@Deprecated
public String createConnectorId(ClientConnector connector) {
return service.generateConnectorId(this, connector);
}

/**
* Gets the next unused numerical id for connector ids.
*
* @since 8.1
*
* @return the next unused numerical id for connector ids, not
* <code>null</code>
*
*/
public String getNextConnectorId() {
assert hasLock();
return String.valueOf(connectorIdSequence++);
}

+ 6
- 0
server/src/test/java/com/vaadin/server/MockVaadinSession.java 查看文件

@@ -64,6 +64,12 @@ public class MockVaadinSession extends VaadinSession {
referenceKeeper.remove();
}

@Override
public String createConnectorId(ClientConnector connector) {
// Don't delegate to service which may be null or a broken mock
return getNextConnectorId();
}

private int closeCount;

private final ReentrantLock lock = new ReentrantLock();

+ 2
- 11
server/src/test/java/com/vaadin/tests/server/component/abstractsinglecomponentcontainer/RemoveFromParentLockingTest.java 查看文件

@@ -15,14 +15,12 @@
*/
package com.vaadin.tests.server.component.abstractsinglecomponentcontainer;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.vaadin.server.MockVaadinSession;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.UI;
@@ -37,14 +35,7 @@ public class RemoveFromParentLockingTest {
}

private static VerticalLayout createTestComponent() {
VaadinSession session = new VaadinSession(null) {
private final ReentrantLock lock = new ReentrantLock();

@Override
public Lock getLockInstance() {
return lock;
}
};
VaadinSession session = new MockVaadinSession(null);

session.getLockInstance().lock();
try {

+ 2
- 0
uitest/src/main/java/com/vaadin/tests/applicationservlet/ServiceInitListeners.java 查看文件

@@ -24,5 +24,7 @@ public class ServiceInitListeners extends AbstractTestUIWithLog {
protected void setup(VaadinRequest request) {
log("Init count: " + TestingServiceInitListener.getInitCount());
log("Request count: " + TestingServiceInitListener.getRequestCount());
log("Connector id count: "
+ TestingServiceInitListener.getConnectorIdCount());
}
}

+ 16
- 0
uitest/src/main/java/com/vaadin/tests/applicationservlet/TestingServiceInitListener.java 查看文件

@@ -18,6 +18,8 @@ package com.vaadin.tests.applicationservlet;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

import com.vaadin.server.ConnectorIdGenerationEvent;
import com.vaadin.server.ConnectorIdGenerator;
import com.vaadin.server.RequestHandler;
import com.vaadin.server.ServiceInitEvent;
import com.vaadin.server.VaadinRequest;
@@ -29,6 +31,7 @@ public class TestingServiceInitListener implements VaadinServiceInitListener {

private static AtomicInteger initCount = new AtomicInteger();
private static AtomicInteger requestCount = new AtomicInteger();
private static AtomicInteger connectorIdCount = new AtomicInteger();

@Override
public void serviceInit(ServiceInitEvent event) {
@@ -43,6 +46,15 @@ public class TestingServiceInitListener implements VaadinServiceInitListener {
return false;
}
});

event.addConnectorIdGenerator(new ConnectorIdGenerator() {
@Override
public String generateConnectorId(
ConnectorIdGenerationEvent event) {
connectorIdCount.incrementAndGet();
return ConnectorIdGenerator.generateDefaultConnectorId(event);
}
});
}

public static int getInitCount() {
@@ -53,4 +65,8 @@ public class TestingServiceInitListener implements VaadinServiceInitListener {
return requestCount.get();
}

public static int getConnectorIdCount() {
return connectorIdCount.get();
}

}

+ 1
- 0
uitest/src/test/java/com/vaadin/tests/applicationservlet/ServiceInitListenersTest.java 查看文件

@@ -28,6 +28,7 @@ public class ServiceInitListenersTest extends SingleBrowserTest {

Assert.assertNotEquals(getLogRow(0), 0, extractCount(getLogRow(0)));
Assert.assertNotEquals(getLogRow(1), 0, extractCount(getLogRow(1)));
Assert.assertNotEquals(getLogRow(2), 0, extractCount(getLogRow(2)));
}

private int extractCount(String logRow) {

正在加载...
取消
保存