Also remove ComponentMissingFromDefaultWidgetsetTest since it's identical to UnknownComponentConnectorTest Change-Id: I4b4b8f40c8376f4ea26b73d41191a3e7e811df01tags/8.0.0.alpha9
@@ -58,6 +58,7 @@ import com.vaadin.client.metadata.TypeData; | |||
import com.vaadin.client.metadata.TypeDataStore; | |||
import com.vaadin.client.metadata.TypeDataStore.MethodAttribute; | |||
import com.vaadin.client.ui.UnknownComponentConnector; | |||
import com.vaadin.client.ui.UnknownExtensionConnector; | |||
import com.vaadin.server.widgetsetutils.metadata.ClientRpcVisitor; | |||
import com.vaadin.server.widgetsetutils.metadata.ConnectorBundle; | |||
import com.vaadin.server.widgetsetutils.metadata.ConnectorInitVisitor; | |||
@@ -1123,6 +1124,8 @@ public class ConnectorBundleLoaderFactory extends Generator { | |||
connectorsByLoadStyle.get(LoadStyle.EAGER)); | |||
eagerBundle.processType(eagerLogger, typeOracle | |||
.findType(UnknownComponentConnector.class.getCanonicalName())); | |||
eagerBundle.processType(eagerLogger, typeOracle | |||
.findType(UnknownExtensionConnector.class.getCanonicalName())); | |||
eagerBundle.processSubTypes(eagerLogger, | |||
typeOracle.getType(ClientRpc.class.getName())); | |||
eagerBundle.processSubTypes(eagerLogger, |
@@ -48,6 +48,7 @@ import com.vaadin.client.communication.JSONSerializer; | |||
import com.vaadin.client.connectors.AbstractRendererConnector; | |||
import com.vaadin.client.metadata.TypeDataStore.MethodAttribute; | |||
import com.vaadin.client.ui.UnknownComponentConnector; | |||
import com.vaadin.client.ui.UnknownExtensionConnector; | |||
import com.vaadin.shared.communication.ClientRpc; | |||
import com.vaadin.shared.communication.ServerRpc; | |||
import com.vaadin.shared.ui.Connect; | |||
@@ -469,7 +470,9 @@ public class ConnectorBundle { | |||
private static boolean isConnected(JClassType type) { | |||
return type.isAnnotationPresent(Connect.class) | |||
|| type.getQualifiedSourceName().equals( | |||
UnknownComponentConnector.class.getCanonicalName()); | |||
UnknownComponentConnector.class.getCanonicalName()) | |||
|| type.getQualifiedSourceName().equals( | |||
UnknownExtensionConnector.class.getCanonicalName()); | |||
} | |||
public static boolean isConnectedComponentConnector(JClassType type) { |
@@ -53,6 +53,7 @@ import com.vaadin.client.metadata.ConnectorBundleLoader; | |||
import com.vaadin.client.metadata.NoDataException; | |||
import com.vaadin.client.metadata.TypeData; | |||
import com.vaadin.client.ui.UnknownComponentConnector; | |||
import com.vaadin.client.ui.UnknownExtensionConnector; | |||
import com.vaadin.client.ui.ui.UIConnector; | |||
import com.vaadin.shared.ApplicationConstants; | |||
import com.vaadin.shared.ui.ui.UIConstants; | |||
@@ -526,7 +527,11 @@ public class ApplicationConfiguration implements EntryPoint { | |||
currentTag = getParentTag(currentTag.intValue()); | |||
} | |||
if (type == null) { | |||
type = UnknownComponentConnector.class; | |||
if (isExtensionType(tag)) { | |||
type = UnknownExtensionConnector.class; | |||
} else { | |||
type = UnknownComponentConnector.class; | |||
} | |||
if (unknownComponents == null) { | |||
unknownComponents = new HashMap<>(); | |||
} | |||
@@ -537,6 +542,20 @@ public class ApplicationConfiguration implements EntryPoint { | |||
return type; | |||
} | |||
private boolean isExtensionType(int tag) { | |||
Integer currentTag = Integer.valueOf(tag); | |||
while (currentTag != null) { | |||
String serverSideClassNameForTag = getServerSideClassNameForTag( | |||
currentTag); | |||
if ("com.vaadin.server.AbstractExtension" | |||
.equals(serverSideClassNameForTag)) { | |||
return true; | |||
} | |||
currentTag = getParentTag(currentTag.intValue()); | |||
} | |||
return false; | |||
} | |||
public void addComponentInheritanceInfo(ValueMap valueMap) { | |||
JsArrayString keyArray = valueMap.getKeyArray(); | |||
for (int i = 0; i < keyArray.length(); i++) { |
@@ -36,6 +36,7 @@ import com.google.gwt.event.dom.client.MouseOutHandler; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.client.ui.UnknownComponentConnector; | |||
import com.vaadin.client.ui.UnknownExtensionConnector; | |||
import com.vaadin.client.ui.VWindow; | |||
import elemental.json.JsonArray; | |||
@@ -229,7 +230,8 @@ public class VUIDLBrowser extends SimpleTree { | |||
int tag) { | |||
Class<? extends ServerConnector> widgetClassByDecodedTag = conf | |||
.getConnectorClassByEncodedTag(tag); | |||
if (widgetClassByDecodedTag == UnknownComponentConnector.class) { | |||
if (widgetClassByDecodedTag == UnknownComponentConnector.class | |||
|| widgetClassByDecodedTag == UnknownExtensionConnector.class) { | |||
return conf.getUnknownServerClassNameByTag(tag) | |||
+ "(NO CLIENT IMPLEMENTATION FOUND)"; | |||
} else { |
@@ -26,6 +26,8 @@ import com.vaadin.client.metadata.ConnectorBundleLoader; | |||
import com.vaadin.client.metadata.NoDataException; | |||
import com.vaadin.client.metadata.TypeData; | |||
import com.vaadin.client.ui.UnknownComponentConnector; | |||
import com.vaadin.client.ui.UnknownExtensionConnector; | |||
import com.vaadin.client.ui.UnknownExtensionConnector; | |||
public class WidgetSet { | |||
/** | |||
@@ -55,33 +57,43 @@ public class WidgetSet { | |||
Class<? extends ServerConnector> classType = resolveInheritedConnectorType( | |||
conf, tag); | |||
if (classType == null || classType == UnknownComponentConnector.class) { | |||
String serverSideName = conf.getUnknownServerClassNameByTag(tag); | |||
UnknownComponentConnector c = GWT | |||
.create(UnknownComponentConnector.class); | |||
c.setServerSideClassName(serverSideName); | |||
Profiler.leave("WidgetSet.createConnector"); | |||
return c; | |||
} else { | |||
/* | |||
* let the auto generated code instantiate this type | |||
*/ | |||
try { | |||
try { | |||
if (classType == null | |||
|| classType == UnknownComponentConnector.class | |||
|| classType == UnknownExtensionConnector.class) { | |||
String serverSideName = conf | |||
.getUnknownServerClassNameByTag(tag); | |||
if (classType == UnknownExtensionConnector.class) { | |||
// Display message in the console for non-visual connectors | |||
getLogger().severe(UnknownComponentConnector | |||
.createMessage(serverSideName)); | |||
return GWT.create(UnknownExtensionConnector.class); | |||
} else { | |||
UnknownComponentConnector c = GWT | |||
.create(UnknownComponentConnector.class); | |||
// Set message to be shown in a widget for visual connectors | |||
c.setServerSideClassName(serverSideName); | |||
return c; | |||
} | |||
} else { | |||
/* | |||
* let the auto generated code instantiate this type | |||
*/ | |||
ServerConnector connector = (ServerConnector) TypeData | |||
.getType(classType).createInstance(); | |||
if (connector instanceof HasJavaScriptConnectorHelper) { | |||
((HasJavaScriptConnectorHelper) connector) | |||
.getJavascriptConnectorHelper().setTag(tag); | |||
} | |||
Profiler.leave("WidgetSet.createConnector"); | |||
return connector; | |||
} catch (NoDataException e) { | |||
Profiler.leave("WidgetSet.createConnector"); | |||
throw new IllegalStateException( | |||
"There is no information about " + classType | |||
+ ". Did you remember to compile the right widgetset?", | |||
e); | |||
} | |||
} catch (NoDataException e) { | |||
throw new IllegalStateException( | |||
"There is no information about " + classType | |||
+ ". Did you remember to compile the right widgetset?", | |||
e); | |||
} finally { | |||
Profiler.leave("WidgetSet.createConnector"); | |||
} | |||
} | |||
@@ -26,6 +26,7 @@ import com.vaadin.client.ApplicationConnection; | |||
import com.vaadin.client.ServerConnector; | |||
import com.vaadin.client.Util; | |||
import com.vaadin.client.ui.UnknownComponentConnector; | |||
import com.vaadin.client.ui.UnknownExtensionConnector; | |||
/** | |||
* Optimized widgetset view panel of the debug window. | |||
@@ -89,7 +90,8 @@ public class OptimizedWidgetsetPanel extends FlowPanel { | |||
break; | |||
} | |||
if (connectorClass != UnknownComponentConnector.class) { | |||
if (connectorClass != UnknownComponentConnector.class | |||
&& connectorClass != UnknownExtensionConnector.class) { | |||
usedConnectors.add(connectorClass.getName()); | |||
} | |||
tag++; |
@@ -31,13 +31,17 @@ public class UnknownComponentConnector extends AbstractComponentConnector { | |||
} | |||
public void setServerSideClassName(String serverClassName) { | |||
getWidget().setCaption("Widgetset '" + GWT.getModuleName() | |||
+ "' does not contain implementation for " + serverClassName | |||
+ ". Check its component connector's @Connect mapping, widgetsets " | |||
getWidget().setCaption(createMessage(serverClassName)); | |||
} | |||
public static String createMessage(String serverClassName) { | |||
return "Widgetset '" + GWT.getModuleName() | |||
+ "' does not contain an implementation for " + serverClassName | |||
+ ". Check the connector's @Connect mapping, the widgetset's " | |||
+ "GWT module description file and re-compile your" | |||
+ " widgetset. In case you have downloaded a vaadin" | |||
+ " add-on package, you might want to refer to " | |||
+ "<a href='http://vaadin.com/using-addons'>add-on " | |||
+ "instructions</a>."); | |||
+ "instructions</a>."; | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
/* | |||
* Copyright 2000-2014 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.client.ui; | |||
import com.vaadin.client.ServerConnector; | |||
import com.vaadin.client.extensions.AbstractExtensionConnector; | |||
/** | |||
* Connector used as a placeholder for extensions that are not present in the | |||
* widgetset. | |||
* | |||
* @since | |||
* @author Vaadin Ltd | |||
*/ | |||
public class UnknownExtensionConnector extends AbstractExtensionConnector { | |||
@Override | |||
protected void extend(ServerConnector target) { | |||
// Noop | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* Copyright 2000-2014 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.tests.extensions; | |||
import com.vaadin.server.AbstractClientConnector; | |||
import com.vaadin.server.AbstractExtension; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.ui.Label; | |||
public class UnknownExtensionHandling extends AbstractTestUI { | |||
// Extension without @Connect counterpart | |||
public static class MyExtension extends AbstractExtension { | |||
@Override | |||
public void extend(AbstractClientConnector target) { | |||
super.extend(target); | |||
} | |||
} | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
Label label = new Label( | |||
"A label with a missing extension, should cause sensible output in the debug window / browser console"); | |||
MyExtension extension = new MyExtension(); | |||
extension.extend(label); | |||
addComponent(label); | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* Copyright 2000-2014 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.tests.components; | |||
import static org.junit.Assert.assertTrue; | |||
import org.junit.Test; | |||
import org.openqa.selenium.WebElement; | |||
import com.vaadin.tests.tb3.MultiBrowserTest; | |||
/** | |||
* Tests that a user is notified about a missing component from the widgetset | |||
*/ | |||
public class UnknownComponentConnectorTest extends MultiBrowserTest { | |||
@Test | |||
public void testConnectorNotFoundInWidgetset() throws Exception { | |||
openTestURL(); | |||
WebElement component = vaadinElementById("no-connector-component"); | |||
assertTrue(component.getText().startsWith( | |||
"Widgetset 'com.vaadin.DefaultWidgetSet' does not contain an " | |||
+ "implementation for com.vaadin.tests.components.UnknownComponentConnector." | |||
+ "ComponentWithoutConnector.")); | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/* | |||
* Copyright 2000-2014 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.tests.extensions; | |||
import java.util.List; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.openqa.selenium.By; | |||
import org.openqa.selenium.WebElement; | |||
import com.vaadin.tests.extensions.UnknownExtensionHandling.MyExtension; | |||
import com.vaadin.tests.tb3.SingleBrowserTest; | |||
public class UnknownExtensionHandlingTest extends SingleBrowserTest { | |||
@Test | |||
public void testUnknownExtensionHandling() { | |||
setDebug(true); | |||
openTestURL(); | |||
openDebugLogTab(); | |||
Assert.assertTrue( | |||
hasMessageContaining(MyExtension.class.getCanonicalName())); | |||
Assert.assertFalse(hasMessageContaining("Hierachy claims")); | |||
} | |||
private boolean hasMessageContaining(String needle) { | |||
List<WebElement> elements = findElements( | |||
By.className("v-debugwindow-message")); | |||
for (WebElement messageElement : elements) { | |||
// Can't use getText() since element isn't scrolled into view | |||
String text = (String) executeScript( | |||
"return arguments[0].textContent", messageElement); | |||
if (text.contains(needle)) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} |