diff options
Diffstat (limited to 'sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org')
95 files changed, 10310 insertions, 0 deletions
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java new file mode 100644 index 0000000000..238cc8c2fa --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + +import org.apache.tuscany.sca.assembly.Base; + + +/** + * Represents an artifact in an SCA contribution. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface Artifact extends Base { + + /** + * Returns the URI that unique identifies the artifact inside the contribution. + * + * @return The artifact URI + */ + String getURI(); + + /** + * Sets the URI that uniquely identifies the artifact inside the contribution. + * + * @param uri The artifact URI + */ + void setURI(String uri); + + /** + * Returns the location of the artifact. + * + * @return The artifact location + */ + String getLocation(); + + /** + * Set the location of the artifact. + * + * @param location The artifact location + */ + void setLocation(String location); + + + /** + * Returns the in-memory model representing the artifact. + * + * @return The model object + */ + <T> T getModel(); + + /** + * Sets the in-memory model representing the artifact. + * + * @param model The model object + */ + void setModel(Object model); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java new file mode 100644 index 0000000000..81b0b08b9d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + +/** + * Constants for the main supported contribution package type. + * + * @version $Rev$ $Date$ + */ +@Deprecated +public interface ContentType { + + /** + * Java compressed contribution package + */ + String JAR = "application/x-compressed"; + + /** + * Filesystem folder contribution package + */ + String FOLDER = "application/vnd.tuscany.folder"; + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java new file mode 100644 index 0000000000..777ba1f986 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java @@ -0,0 +1,126 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Extensible; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of an SCA contribution. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface Contribution extends Artifact, Extensible { + + /** + * Default location of contribution metadata in an SCA contribution. + */ + String SCA_CONTRIBUTION_META = "META-INF/sca-contribution.xml"; + + /** + * Default location of a generated contribution metadata in an SCA contribution. + */ + String SCA_CONTRIBUTION_GENERATED_META = "META-INF/sca-contribution-generated.xml"; + + /** + * Returns a list of exports based on the contribution metadata. + * + * @return The list of exports in this contribution + */ + List<Export> getExports(); + + /** + * Returns a list of imports based on the contribution metadata. + * + * @return The list of imports in this contribution + */ + List<Import> getImports(); + + /** + * Returns the list of deployable composites in the contribution. + * + * @return The list of deployable composites + */ + List<Composite> getDeployables(); + + /** + * Returns the list of artifacts in the contribution. + * + * @return The list of artifacts in the contribution + */ + List<Artifact> getArtifacts(); + + /** + * Returns the model resolver for the models representing the artifacts + * visible in the scope of this contribution. + * + * @return The model resolver + */ + ModelResolver getModelResolver(); + + /** + * Sets the model resolver for the models representing the artifacts + * visible in the scope of this contribution. + * + * @param modelResolver The model resolver + */ + void setModelResolver(ModelResolver modelResolver); + + /** + * Returns the list of contributions that this contribution depends on. + * + * @return + */ + List<Contribution> getDependencies(); + + /** + * Returns the ClassLoader used to load classes and resources from + * this contribution + * + * FIXME Remove this, the base contribution model should not depend + * on Java ClassLoaders. + * + * @return The contribution ClassLoader + */ + ClassLoader getClassLoader(); + + /** + * Sets the ClassLoader used to load classes and resources from + * this contribution + * + * FIXME Remove this, the base contribution model should not depend + * on Java ClassLoaders. + * + * @param classLoader the contribution class loader + */ + void setClassLoader(ClassLoader classLoader); + + /** + * Get a list of mime types that apply to this contribution archive + * @return + */ + Set<String> getTypes(); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java new file mode 100644 index 0000000000..5937d535d0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + + +/** + * A factory for the contribution model. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface ContributionFactory { + + /** + * Create a contribution model object + * + * @return The new contribution model object + */ + Contribution createContribution(); + + /** + * Create a contribution metadata model object + * + * @return The new contribution metadata model object + */ + ContributionMetadata createContributionMetadata(); + + /** + * Create an artifact model object + * + * @return The new artifact model object + */ + Artifact createArtifact(); + + /** + * Create a default import model object. + * + * @return the new default import model object + */ + DefaultImport createDefaultImport(); + + /** + * Create a default export model object. + * + * @return the new default export model object + */ + DefaultExport createDefaultExport(); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java new file mode 100644 index 0000000000..a62d7155c9 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Extensible; + +/** + * The representation of SCA contribution metadata. + * + * @version $Rev$ $Date$ + */ +public interface ContributionMetadata extends Base, Extensible { + + /** + * Returns the spec version of the contribution metadata used to build this model + * + * @return the spec version used to build this model + */ + String getSpecVersion(); + + /** + * Sets the spec version of the contribution metadata used to build this model + * + * @param specVersion the spec version used to build this model + */ + void setSpecVersion(String specVersion); + + /** + * Returns a list of exports based on the contribution metadata. + * + * @return The list of exports + */ + List<Export> getExports(); + + /** + * Returns a list of imports based on the contribution metadata. + * + * @return The list of imports + */ + List<Import> getImports(); + + /** + * Returns the list of deployable based on the contribution metadata. + * + * @return The list of deployable composites + */ + List<Composite> getDeployables(); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java new file mode 100644 index 0000000000..98954c288a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + +import org.apache.tuscany.sca.contribution.impl.ContributionFactoryImpl; + + +/** + * Default implementation of a contribution model factory. + * + * @version $Rev$ $Date$ + */ +public class DefaultContributionFactory extends ContributionFactoryImpl { + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java new file mode 100644 index 0000000000..b2eddb8336 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + + +/** + * The representation of an export that exports all artifacts in + * a contribution. + * + * @version $Rev$ $Date$ + */ +public interface DefaultExport extends Export { +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java new file mode 100644 index 0000000000..4b3d157554 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + + +/** + * The representation of a default import that imports artifacts from + * all contributions. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface DefaultImport extends Import { +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java new file mode 100644 index 0000000000..a6e5afe7b8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + +import org.apache.tuscany.sca.assembly.Extensible; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of an export. + * + * @version $Rev$ $Date$ + */ +public interface Export extends Extensible { + + /** + * Returns the model resolver for the models representing artifacts + * made available by this export. + * + * @return The model resolver + */ + ModelResolver getModelResolver(); + + /** + * Sets the model resolver for the models representing artifacts + * made available by this export. + * + * @param modelResolver + */ + void setModelResolver(ModelResolver modelResolver); + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java new file mode 100644 index 0000000000..450476b79b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + +import org.apache.tuscany.sca.assembly.Extensible; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * The representation of an import. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface Import extends Extensible { + + /** + * Returns the model resolver for the models representing artifacts + * made available by this import. + * + * @return The model resolver + */ + ModelResolver getModelResolver(); + + /** + * Sets the model resolver for the models representing artifacts + * made available by this import. + * + * @param modelResolver The model resolver + */ + void setModelResolver(ModelResolver modelResolver); + + /** + * Verify that a specific export actually exports what is being imported. + * + * @param export The Exported being verified + * @return true/false + */ + boolean match(Export export); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java new file mode 100644 index 0000000000..c6c0aff737 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution; + +/** + * Constants for the main supported contribution package types. + * + * @version $Rev$ $Date$ + */ +public interface PackageType { + + /** + * Java compressed contribution package + */ + String JAR = "application/java-archive"; + + /** + * Zip archive contribution package + */ + String ZIP = "application/zip"; + + /** + * Filesystem folder contribution package + */ + String FOLDER = "application/vnd.tuscany.folder"; + + + String BUNDLE = "application/osgi.bundle"; + + /** + * Java EE Web Application Archive + */ + String WAR = "application/war"; + + /** + * Java EE Enterprise Application Archive + */ + String EAR = "application/ear"; + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java new file mode 100644 index 0000000000..a362e97fc6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java @@ -0,0 +1,94 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.impl; + +import org.apache.tuscany.sca.contribution.Artifact; + + +/** + * The model representing an artifact in a contribution. + * + * @version $Rev$ $Date$ + */ +class ArtifactImpl implements Artifact { + private String uri; + private String location; + private Object model; + private boolean unresolved; + + ArtifactImpl() { + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public <T> T getModel() { + return (T) model; + } + + public void setModel(Object model) { + this.model = model; + } + + public boolean isUnresolved() { + return unresolved; + } + + public void setUnresolved(boolean unresolved) { + this.unresolved = unresolved; + } + + @Override + public int hashCode() { + return uri.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof Artifact) { + return uri.equals(((Artifact)obj).getURI()); + } else { + return false; + } + } + } + + @Override + public String toString() { + return "Artifact:" + uri + "\n" + + "at: " + location; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java new file mode 100644 index 0000000000..64bfb20bed --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.impl; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ContributionMetadata; +import org.apache.tuscany.sca.contribution.DefaultExport; +import org.apache.tuscany.sca.contribution.DefaultImport; + + +/** + * Default implementation of a contribution model factory. + * + * @version $Rev$ $Date$ + */ +public class ContributionFactoryImpl implements ContributionFactory { + + protected ContributionFactoryImpl() { + } + + public Contribution createContribution() { + return new ContributionImpl(); + } + + public ContributionMetadata createContributionMetadata() { + return new ContributionMetadataImpl(); + } + + public Artifact createArtifact() { + return new ArtifactImpl(); + } + + public DefaultExport createDefaultExport() { + return new DefaultExportImpl(); + } + + public DefaultImport createDefaultImport() { + return new DefaultImportImpl(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java new file mode 100644 index 0000000000..c31763151d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java @@ -0,0 +1,158 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.impl; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of a deployed contribution + * + * @version $Rev$ $Date$ + */ +class ContributionImpl extends ExtensibleImpl implements Contribution { + private String uri; + private String location; + private Object model; + private byte[] contents; + private List<Export> exports = new ArrayList<Export>(); + private List<Import> imports = new ArrayList<Import>(); + private List<Composite> deployables = new ArrayList<Composite>(); + private List<Artifact> artifacts = new ArrayList<Artifact>(); + private List<Contribution> dependencies = new ArrayList<Contribution>(); + private ModelResolver modelResolver; + private Set<String> types = new HashSet<String>(); + + // FIXME remove this dependency on Java ClassLoaders + private ClassLoader classLoader; + + ContributionImpl() { + } + + public String getLocation() { + return this.location; + } + + public void setLocation(String location) { + this.location = location; + } + + //FIXME Remove dependency on Java ClassLoaders + public ClassLoader getClassLoader() { + return classLoader; + } + + //FIXME Remove dependency on Java ClassLoaders + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + + public String getURI() { + return this.uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public <T> T getModel() { + return (T) model; + } + + public void setModel(Object model) { + this.model = model; + } + + public byte[] getContents() { + return contents; + } + + public void setContents(byte[] contents) { + this.contents = contents; + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + + public List<Contribution> getDependencies() { + return dependencies; + } + + public List<Export> getExports() { + return exports; + } + + public List<Import> getImports() { + return imports; + } + + public List<Composite> getDeployables() { + return deployables; + } + + public List<Artifact> getArtifacts() { + return artifacts; + } + + @Override + public int hashCode() { + return uri.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof Artifact) { + return uri.equals(((Artifact)obj).getURI()); + } else { + return false; + } + } + } + + @Override + public String toString() { + return "Contribution : " + uri + " \n" + + "from: " + location; + } + + public Set<String> getTypes() { + return types; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java new file mode 100644 index 0000000000..e2397c6f26 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl; +import org.apache.tuscany.sca.contribution.ContributionMetadata; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.Import; + +/** + * The representation of a deployed contribution + * + * @version $Rev$ $Date$ + */ +class ContributionMetadataImpl extends ExtensibleImpl implements ContributionMetadata { + + private String specVersion = "undefined"; + private List<Export> exports = new ArrayList<Export>(); + private List<Import> imports = new ArrayList<Import>(); + private List<Composite> deployables = new ArrayList<Composite>(); + private boolean unresolved; + + ContributionMetadataImpl() { + } + + public String getSpecVersion() { + return specVersion; + } + + public void setSpecVersion(String specVersion) { + this.specVersion = specVersion; + } + + public List<Export> getExports() { + return exports; + } + + public List<Import> getImports() { + return imports; + } + + public List<Composite> getDeployables() { + return deployables; + } + + public boolean isUnresolved() { + return unresolved; + } + + public void setUnresolved(boolean unresolved) { + this.unresolved = unresolved; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java new file mode 100644 index 0000000000..d4614e5427 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.impl; + +import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl; +import org.apache.tuscany.sca.contribution.DefaultExport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of an export for the contribution + * + * @version $Rev$ $Date$ + */ +public class DefaultExportImpl extends ExtensibleImpl implements DefaultExport { + private ModelResolver modelResolver; + + protected DefaultExportImpl() { + super(); + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java new file mode 100644 index 0000000000..7ab535f916 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java @@ -0,0 +1,56 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.impl; + +import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl; +import org.apache.tuscany.sca.contribution.DefaultExport; +import org.apache.tuscany.sca.contribution.DefaultImport; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of an import for the contribution + * + * @version $Rev$ $Date$ + */ +public class DefaultImportImpl extends ExtensibleImpl implements DefaultImport { + private ModelResolver modelResolver; + + protected DefaultImportImpl() { + super(); + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + + + public boolean match(Export export) { + if (export instanceof DefaultExport) { + return true; + } + return false; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java new file mode 100644 index 0000000000..886c61c00a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java; + +import org.apache.tuscany.sca.contribution.java.impl.JavaImportExportFactoryImpl; + +/** + * Default Java Import/Export Factory implementation + * + * @version $Rev$ $Date$ + */ +public class DefaultJavaImportExportFactory extends JavaImportExportFactoryImpl implements JavaImportExportFactory { +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java new file mode 100644 index 0000000000..41e93ec148 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java; + +import org.apache.tuscany.sca.contribution.Export; + +/** + * Base Java Export model interface + * + * @version $Rev$ $Date$ + */ +public interface JavaExport extends Export { + /** + * Get java package that identifies the import + * + * @return The package name + */ + String getPackage(); + + /** + * Set java package that identifies the import + * + * @param packageName The package name + */ + void setPackage(String packageName); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java new file mode 100644 index 0000000000..d3568f6283 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java; + +import org.apache.tuscany.sca.contribution.Import; + +/** + * Base Java Import model interface + * + * @version $Rev$ $Date$ + */ +public interface JavaImport extends Import { + + /** + * Get the location used to resolve the definitions for this import + * + * @return The import location + */ + String getLocation(); + + /** + * Set the location used to resolve the definitions for this import + * + * @param location The import location + */ + void setLocation(String location); + + /** + * Get java package that identifies the import + * + * @return The package name + */ + String getPackage(); + + /** + * Set java package that identifies the import + * + * @param packageName The package name + */ + void setPackage(String packageName); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java new file mode 100644 index 0000000000..ee94d889ad --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java; + +/** + * Base Java Import/Export model factory + * + * @version $Rev$ $Date$ + */ +public interface JavaImportExportFactory { + + /** + * Create a java import model object + * + * @return The new JavaImport model object + */ + JavaImport createJavaImport(); + + /** + * Create a java export model object + * + * @return The new JavaExport model object + */ + JavaExport createJavaExport(); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java new file mode 100644 index 0000000000..1ba394dde9 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java @@ -0,0 +1,182 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.java.JavaImport; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.DefaultDelegatingModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * A Model Resolver for ClassReferences. + * + * @version $Rev$ $Date$ + */ +public class ClassLoaderModelResolver extends URLClassLoader implements ModelResolver { + private WeakReference<Contribution> contribution; + private ProcessorContext context; + private Map<String, ModelResolver> importResolvers = new HashMap<String, ModelResolver>(); + + // a space to pass back the contribution that was used to resolve + // a class via an import + private Contribution contributionContainingClass; + + private static ClassLoader parentClassLoader(Contribution contribution) { + if (contribution.getClassLoader() != null) { + return contribution.getClassLoader(); + } + ClassLoader parentClassLoader = ServiceDiscovery.getInstance().getContextClassLoader(); + return parentClassLoader; + } + + private static URL[] getContributionURLs(final Contribution contribution) throws IOException { + if (contribution.getClassLoader() != null) { + // Do not include the contribution url + return new URL[0]; + } + List<URL> urls = new ArrayList<URL>(); + urls.add(new URL(contribution.getLocation())); + urls.addAll(ContributionHelper.getNestedJarUrls(contribution)); + return urls.toArray(new URL[urls.size()]); + } + + public ClassLoaderModelResolver(final Contribution contribution, FactoryExtensionPoint modelFactories) throws IOException { + super(getContributionURLs(contribution), parentClassLoader(contribution)); + this.contribution = new WeakReference<Contribution>(contribution); + // Index Java import resolvers by package name + Map<String, List<ModelResolver>> resolverMap = new HashMap<String, List<ModelResolver>>(); + for (Import import_: this.contribution.get().getImports()) { + if (import_ instanceof JavaImport) { + JavaImport javaImport = (JavaImport)import_; + List<ModelResolver> resolvers = resolverMap.get(javaImport.getPackage()); + if (resolvers == null) { + resolvers = new ArrayList<ModelResolver>(); + resolverMap.put(javaImport.getPackage(), resolvers); + } + resolvers.add(javaImport.getModelResolver()); + } + } + + // Create a delegating model resolver for each imported package + for (Map.Entry<String, List<ModelResolver>> entry: resolverMap.entrySet()) { + importResolvers.put(entry.getKey(), new DefaultDelegatingModelResolver(entry.getValue())); + } + } + + public void addModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + if (!(unresolved instanceof ClassReference)) { + return unresolved; + } + + try { + this.context = context; + contributionContainingClass = contribution.get(); + + // Load the class and return a class reference for it + String className = ((ClassReference)unresolved).getClassName(); + Class<?> clazz = Class.forName(className, false, this); + ClassReference classReference = new ClassReference(clazz); + classReference.setContributionContainingClass(contributionContainingClass); + contributionContainingClass = null; + return modelClass.cast(classReference); + + } catch (ClassNotFoundException e) { + return unresolved; + } + } + + @Override + public URL findResource(String name) { + + //TODO delegate to the Java import resolvers + + URL url = super.findResource(name); + return url; + } + + @Override + public Enumeration<URL> findResources(String name) throws IOException { + + //TODO delegate to the Java import resolvers + //Enumeration<URL> importedResources; + + Enumeration<URL> resources = super.findResources(name); + List<URL> allResources = new ArrayList<URL>(); + //for (; importedResources.hasMoreElements(); ) { + // allResources.add(importedResources.nextElement()); + //} + for (; resources.hasMoreElements(); ) { + allResources.add(resources.nextElement()); + } + return Collections.enumeration(allResources); + } + + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + + // Extract the package name + int d = name.lastIndexOf('.'); + String packageName; + if (d != -1) { + packageName = name.substring(0, d); + } else { + packageName = null; + } + + // First try to load the class using the Java import resolvers + ModelResolver importResolver = importResolvers.get(packageName); + if (importResolver != null) { + ClassReference classReference = importResolver.resolveModel(ClassReference.class, new ClassReference(name), context); + if (!classReference.isUnresolved()) { + contributionContainingClass = classReference.getContributionContainingClass(); + return classReference.getJavaClass(); + } + } + + // Next, try to load the class from the current contribution + Class<?> clazz = super.findClass(name); + return clazz; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java new file mode 100644 index 0000000000..25b3eae350 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java @@ -0,0 +1,386 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.java.JavaImport; + + +public class ContributionClassLoader extends URLClassLoader { +// public class ContributionClassLoader { + + private Contribution contribution; + // private b urlClassLoader; + + /** + * Constructor for contribution ClassLoader + * + * @param contribution + * @param parent + * @throws MalformedURLException + */ + public ContributionClassLoader(Contribution contribution, final ClassLoader parent) { + super(new URL[0], parent); + // Note that privileged use of getContextClassLoader have been promoted to callers. + // super(new URL[0], parent == null?Thread.currentThread().getContextClassLoader(): null); + this.contribution = contribution; + if (contribution.getLocation() != null) { + try { + this.addURL(new URL(contribution.getLocation())); + for (URL url : ContributionHelper.getNestedJarUrls(contribution)) { + this.addURL(url); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + /* + * Return the ClassLoader corresponding to a contribution providing an export + * Create a new ClassLoader for the contribution if one does not exist + */ + private ClassLoader getExportClassLoader(Contribution exportingContribution) { + ClassLoader cl = exportingContribution.getClassLoader(); + if (!(cl instanceof ContributionClassLoader)) { + if (cl == null) { + cl = getParent(); + } + + cl = new ContributionClassLoader(exportingContribution, cl); + exportingContribution.setClassLoader(cl); + } + return cl; + } + + /* (non-Javadoc) + * @see java.net.URLClassLoader#findClass(java.lang.String) + * + * Search path for class: + * This contribution + * Imported contributions + */ + @Override + protected Class<?> findClass(String className) throws ClassNotFoundException { + + Class<?> clazz = null; + try { + clazz = findClassFromContribution(className); + } catch (ClassNotFoundException e) { + + for (Import import_ : this.contribution.getImports()) { + if (classNameMatchesImport(className, import_)) { + // Delegate the resolution to the imported contribution + for (Contribution exportingContribution : ((JavaImportModelResolver)import_.getModelResolver()).getExportContributions()) { + + ClassLoader exportClassLoader = getExportClassLoader(exportingContribution); + if (exportClassLoader instanceof ContributionClassLoader) { + + for (Export export : exportingContribution.getExports()) { + try { + if (import_.match(export)) { + clazz = ((ContributionClassLoader)exportClassLoader).findClassFromContribution(className); + break; + } + } catch (ClassNotFoundException e1) { + continue; + } + + } + if (clazz != null) break; + } + } + if (clazz != null) break; + } + } + + if (clazz == null) throw e; + } + return clazz; + } + + + /* (non-Javadoc) + * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) + * + * Search path for class: + * Parent ClassLoader + * This contribution + * Imported contributions + * + */ + @Override + protected synchronized Class<?> loadClass(String className, boolean resolveClass) + throws ClassNotFoundException { + + Class<?> clazz = null; + try { + + if (this.getParent() != null) + clazz = this.getParent().loadClass(className); + + } catch (ClassNotFoundException e) { + } + + if (clazz == null) + clazz = findClass(className); + + + if (resolveClass) + this.resolveClass(clazz); + return clazz; + + } + + + + /* + * (non-Javadoc) + * + * @see java.net.URLClassLoader#findResource(java.lang.String) + */ + @Override + public URL findResource(String name) { + + URL url = findResourceFromContribution(name); + + if (url == null) { + for (Import import_ : this.contribution.getImports()) { + if (resourceNameMatchesImport(name, import_)) { + // Delegate the resolution to the imported contribution + for (Contribution exportingContribution : ((JavaImportModelResolver)import_.getModelResolver()).getExportContributions()) { + + ClassLoader exportClassLoader = getExportClassLoader(exportingContribution); + if (exportClassLoader instanceof ContributionClassLoader) { + + for (Export export : exportingContribution.getExports()) { + if (import_.match(export)) { + url = ((ContributionClassLoader)exportClassLoader).findResourceFromContribution(name); + if (url != null) break; + } + } + if (url != null) break; + } + } + if (url != null) break; + } + } + + } + return url; + } + + + /* (non-Javadoc) + * @see java.net.URLClassLoader#findResources(java.lang.String) + */ + @Override + public Enumeration<URL> findResources(String name) throws IOException { + + return Collections.enumeration(findResourceSet(name)); + } + + + + + /* (non-Javadoc) + * @see java.lang.ClassLoader#getResource(java.lang.String) + * + * Find a resource. + * Search path for resource: + * Parent ClassLoader + * This contribution + * Imported contributions + */ + @Override + public URL getResource(String resName) { + + URL resource = null; + + if (this.getParent() != null) { + resource = this.getParent().getResource(resName); + } + if (resource == null) + resource = findResource(resName); + + return resource; + } + + + + /* (non-Javadoc) + * @see java.lang.ClassLoader#getResources(java.lang.String) + * + * Return list of resources from this contribution, resources + * imported through imported contributions and resources from parent + * ClassLoader. + */ + @Override + public Enumeration<URL> getResources(String resName) throws IOException { + + HashSet<URL> resourceSet = findResourceSet(resName); + addEnumerationToCollection(resourceSet, super.getResources(resName)); + + return Collections.enumeration(resourceSet); + } + + + /* + * Find set of resources + */ + private HashSet<URL> findResourceSet(String name) throws IOException { + + HashSet<URL> resources = new HashSet<URL>(); + + addEnumerationToCollection(resources, super.findResources(name)); + + for (Import import_ : this.contribution.getImports()) { + if (!(import_ instanceof JavaImport)) { + continue; + } + if (resourceNameMatchesImport(name, import_)) { + // Delegate the resolution to the imported contribution + for (Contribution exportingContribution : ((JavaImportModelResolver)import_.getModelResolver()).getExportContributions()) { + + ClassLoader exportClassLoader = getExportClassLoader(exportingContribution); + if (exportClassLoader instanceof ContributionClassLoader) { + + for (Export export : exportingContribution.getExports()) { + if (import_.match(export)) { + addEnumerationToCollection(resources, + ((ContributionClassLoader)exportClassLoader).findResources(name)); + } + } + } + } + } + } + + return resources; + } + + + /* + * Find class from contribution. If class has already been loaded, return loaded class. + */ + private Class<?> findClassFromContribution(String className) throws ClassNotFoundException { + + Class<?> clazz = findLoadedClass(className); + if (clazz == null) + clazz = super.findClass(className); + return clazz; + + } + + /* + * Find resource from contribution. + */ + private URL findResourceFromContribution(String name) { + + return super.findResource(name); + } + + /** + * Check if a class name matches an import statement. + * Class matches if the package name used in <import.java/> matches + * + * @param name Name of class + * @param import_ SCA contribution import + * @return true if this is a matching import + */ + private boolean classNameMatchesImport(String name, Import import_) { + + if (import_ instanceof JavaImport && name != null && name.lastIndexOf('.') > 0) { + JavaImport javaImport = (JavaImport) import_; + + String packageName = name.substring(0, name.lastIndexOf('.')); + if (javaImport.getPackage().endsWith(".*")) { + String prefix = javaImport.getPackage().substring(0, javaImport.getPackage().length() -1); + if (packageName.startsWith(prefix)) { + return true; + } + } else { + return packageName.equals(javaImport.getPackage()); + } + } + + return false; + } + + /** + * Check if a resource name matches an import statement. + * Resource matches if package/namespace match the directory of resource. + * + * @param name Name of resource + * @param import_ SCA contribution import + * @return true if this is a matching import + */ + private boolean resourceNameMatchesImport(String name, Import import_) { + + + if (name == null || name.lastIndexOf('/') <= 0) + return false; + else if (import_ instanceof JavaImport) { + JavaImport javaImport = (JavaImport) import_; + + if (javaImport.getPackage().endsWith(".*")) { + String packageName = name.substring(0, name.lastIndexOf('/')).replace('/', '.'); + String prefix = javaImport.getPackage().substring(0, javaImport.getPackage().length() -1); + if (packageName.startsWith(prefix)) { + return true; + } + } else { + // 'name' is a resource : contains "/" as separators + // Get package name from resource name + String packageName = name.substring(0, name.lastIndexOf('/')); + return packageName.equals(javaImport.getPackage().replaceAll("\\.", "/")); + } + } + return false; + } + + /* + * Add an enumeration to a Collection + */ + private <T extends Object> void addEnumerationToCollection(Collection<T> collection, Enumeration<T> enumeration) { + + while (enumeration.hasMoreElements()) + collection.add(enumeration.nextElement()); + } + + + @Override + public String toString() { + return "SCA Contribution ClassLoader location: " + contribution.getLocation() + " parent ClassLoader: " + getParent(); + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionHelper.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionHelper.java new file mode 100644 index 0000000000..be175d000e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionHelper.java @@ -0,0 +1,96 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.java.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; + +public class ContributionHelper { + + public static List<URL> getNestedJarUrls(final Contribution contribution) throws IOException { + List<URL> urls = new ArrayList<URL>(); + boolean isZipContribution = contribution.getLocation().endsWith(".zip"); + URI uri = URI.create(contribution.getLocation()); + boolean isFolderContribution = !isZipContribution && uri.getScheme().equals("file") && new File(uri.getSchemeSpecificPart()).isDirectory(); + if (isZipContribution || isFolderContribution) { + for (Artifact a : contribution.getArtifacts()) { + if (a.getLocation().endsWith(".jar")) { + if (isZipContribution) { + urls.add(createTempJar(a, contribution)); + } else { + urls.add(new URL(a.getLocation())); + } + } + } + } + return urls; + } + + /** + * URLClassLoader doesn't seem to work with URLs to jars within an archive so as a work around + * copy the jar to a temp file and use the url to that. + */ + private static URL createTempJar(Artifact artifact, Contribution contribution) throws IOException { + FileOutputStream fileOutputStream = null; + ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(new File(URI.create(contribution.getLocation())))); + try { + ZipEntry zipEntry = zipInputStream.getNextEntry(); + while (zipEntry != null) { + if (artifact.getLocation().endsWith(zipEntry.getName())) { + + String tempName = ("tmp." + artifact.getURI().substring(0, artifact.getURI().length() - 3)).replace('/', '.'); + File tempFile = File.createTempFile(tempName, ".jar"); + tempFile.deleteOnExit(); + fileOutputStream = new FileOutputStream(tempFile); + + byte[] buf = new byte[2048]; + int n; + while ((n = zipInputStream.read(buf, 0, buf.length)) > -1) { + fileOutputStream.write(buf, 0, n); + } + + fileOutputStream.close(); + zipInputStream.closeEntry(); + + return tempFile.toURI().toURL(); + + } + zipEntry = zipInputStream.getNextEntry(); + } + } finally { + zipInputStream.close(); + if (fileOutputStream != null) { + fileOutputStream.close(); + } + } + + throw new IllegalStateException(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java new file mode 100644 index 0000000000..c0bd9465e4 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java @@ -0,0 +1,59 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl; +import org.apache.tuscany.sca.contribution.java.JavaExport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * Implementation of a Java Import model + * + * @version $Rev$ $Date$ + */ +public class JavaExportImpl extends ExtensibleImpl implements JavaExport { + private ModelResolver modelResolver; + + /** + * Java package being exported + */ + private String packageName; + + public JavaExportImpl() { + super(); + } + + public String getPackage() { + return this.packageName; + } + + public void setPackage(String packageName) { + this.packageName = packageName; + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java new file mode 100644 index 0000000000..9b02ce4abb --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java @@ -0,0 +1,77 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import org.apache.tuscany.sca.contribution.java.JavaExport; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * A model resolver for Java exports. + * + * @version $Rev$ $Date$ + */ +public class JavaExportModelResolver implements ModelResolver { + + private JavaExport export; + private ModelResolver resolver; + + public JavaExportModelResolver(JavaExport export, ModelResolver resolver) { + this.export = export; + this.resolver = resolver; + } + + public void addModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + if (!(unresolved instanceof ClassReference)) { + return unresolved; + } + + // Filter package name + ClassReference classReference = (ClassReference)unresolved; + String className = classReference.getClassName(); + int d = className.lastIndexOf('.'); + String packageName; + if (d != -1) { + packageName = className.substring(0, d); + } else { + packageName = ""; + } + if (export.getPackage().equals(packageName)) { + + // Package matches the exported package, delegate to the + // contribution's resolver + return resolver.resolveModel(modelClass, unresolved, context); + } else { + + // Package is not exported, return the unresolved object + return unresolved; + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java new file mode 100644 index 0000000000..bfa89d02fe --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java @@ -0,0 +1,147 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.contribution.java.JavaExport; +import org.apache.tuscany.sca.contribution.java.JavaImportExportFactory; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Artifact processor for Java Export + * + * @version $Rev$ $Date$ + */ +public class JavaExportProcessor implements StAXArtifactProcessor<JavaExport> { + private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200912"; + + private static final QName EXPORT_JAVA = new QName(SCA11_NS, "export.java"); + + private static final String PACKAGE = "package"; + + private final JavaImportExportFactory factory; + + public JavaExportProcessor(FactoryExtensionPoint modelFactories) { + super(); + this.factory = modelFactories.getFactory(JavaImportExportFactory.class); + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-java-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + public QName getArtifactType() { + return EXPORT_JAVA; + } + + public Class<JavaExport> getModelType() { + return JavaExport.class; + } + + /** + * Process <export package=""/> + */ + public JavaExport read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException { + JavaExport javaExport = this.factory.createJavaExport(); + QName element = null; + + try { + while (reader.hasNext()) { + int event = reader.getEventType(); + switch (event) { + case START_ELEMENT: + element = reader.getName(); + + // Read <export.java> + if (EXPORT_JAVA.equals(element)) { + String packageName = reader.getAttributeValue(null, PACKAGE); + if (packageName == null) { + error(context.getMonitor(), "AttributePackageMissing", reader); + //throw new ContributionReadException("Attribute 'package' is missing"); + } else + javaExport.setPackage(packageName); + } + break; + case XMLStreamConstants.END_ELEMENT: + if (EXPORT_JAVA.equals(reader.getName())) { + return javaExport; + } + break; + } + + //Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + } + catch (XMLStreamException e) { + ContributionReadException ex = new ContributionReadException(e); + error(context.getMonitor(), "XMLStreamException", reader, ex); + } + + return javaExport; + } + + public void write(JavaExport javaExport, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException { + + // Write <export.java> + writer.writeStartElement(EXPORT_JAVA.getNamespaceURI(), EXPORT_JAVA.getLocalPart()); + + if (javaExport.getPackage() != null) { + writer.writeAttribute(PACKAGE, javaExport.getPackage()); + } + + writer.writeEndElement(); + } + + public void resolve(JavaExport javaExport, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + + if (javaExport.getPackage() != null) + // Initialize the export resolver + javaExport.setModelResolver(new JavaExportModelResolver(javaExport, resolver)); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java new file mode 100644 index 0000000000..3bf9e54774 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import org.apache.tuscany.sca.contribution.java.JavaExport; +import org.apache.tuscany.sca.contribution.java.JavaImport; +import org.apache.tuscany.sca.contribution.java.JavaImportExportFactory; + +/** + * Java Import/Export Factory implementation + * + * @version $Rev$ $Date$ + */ +public class JavaImportExportFactoryImpl implements JavaImportExportFactory { + + public JavaImport createJavaImport() { + return new JavaImportImpl(); + } + + public JavaExport createJavaExport() { + return new JavaExportImpl(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java new file mode 100644 index 0000000000..f2fdb3278e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java @@ -0,0 +1,111 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.java.JavaExport; +import org.apache.tuscany.sca.contribution.java.JavaImport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * Implementation of a Java Import model + * + * @version $Rev$ $Date$ + */ +public class JavaImportImpl extends ExtensibleImpl implements JavaImport { + private ModelResolver modelResolver; + private List<Contribution> contributions; + /** + * Java package name being imported + */ + private String packageName; + /** + * Contribution URI where the artifact is imported from + */ + private String location; + + public JavaImportImpl() { + super(); + } + + public String getLocation() { + return this.location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getPackage() { + return this.packageName; + } + + public void setPackage(String packageName) { + this.packageName = packageName; + } + + public ModelResolver getModelResolver() { + return this.modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + public List<Contribution> getExportContributions() { + return contributions; + } + + public void setExportContributions(List<Contribution> contributions) { + this.contributions = contributions; + } + + /** + * Match a JavaImport to a given JavaExport based on : + * location is not provided + * import and export packages match + */ + public boolean match(Export export) { + if(export instanceof JavaExport) { + JavaExport javaExport = (JavaExport)export; + String exportedPackage = javaExport.getPackage(); + if (packageName.equals(exportedPackage)) { + return true; + } else { + if (packageName.endsWith(".*")) { + String prefix = packageName.substring(0, packageName.length() - 1); + if (exportedPackage.startsWith(prefix)) { + return true; + } + } + } + } + + return false; + } + + @Override + public String toString() { + return String.valueOf(packageName); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java new file mode 100644 index 0000000000..344e730bdc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import java.util.List; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * A JavaImport specific model resolver. This model resolver is temporary + * and provides the ContributionClassLoader with the list of exporting + * contributions that it currently needs. + * + * FIXME Remove this class after the ContributionClassLoader is simplified + * and cleaned up. + * + * @version $Rev$ $Date$ + */ +public class JavaImportModelResolver implements ModelResolver { + + private ModelResolver modelResolver; + private List<Contribution> contributions; + + public JavaImportModelResolver(List<Contribution> contributions, ModelResolver modelResolver) { + this.modelResolver = modelResolver; + this.contributions = contributions; + } + + public List<Contribution> getExportContributions() { + return contributions; + } + + public void addModel(Object resolved, ProcessorContext context) { + modelResolver.addModel(resolved, context); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + return modelResolver.removeModel(resolved, context); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + return modelResolver.resolveModel(modelClass, unresolved, context); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java new file mode 100644 index 0000000000..a199f6874c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java @@ -0,0 +1,153 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.java.impl; + +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.contribution.java.JavaImport; +import org.apache.tuscany.sca.contribution.java.JavaImportExportFactory; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Artifact Processor for Java Imports + * + * @version $Rev$ $Date$ + */ +public class JavaImportProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor<JavaImport> { + private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200912"; + + private static final QName IMPORT_JAVA = new QName(SCA11_NS, "import.java"); + + private static final String PACKAGE = "package"; + private static final String LOCATION = "location"; + + private final JavaImportExportFactory factory; + + public JavaImportProcessor(FactoryExtensionPoint modelFactories) { + super(); + this.factory = modelFactories.getFactory(JavaImportExportFactory.class); + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-java-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + public QName getArtifactType() { + return IMPORT_JAVA; + } + + public Class<JavaImport> getModelType() { + return JavaImport.class; + } + + /** + * Process <import.java package="" location=""/> + */ + public JavaImport read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException { + JavaImport javaImport = this.factory.createJavaImport(); + QName element = null; + + try { + while (reader.hasNext()) { + int event = reader.getEventType(); + switch (event) { + case START_ELEMENT: + element = reader.getName(); + + // Read <import.java> + if (IMPORT_JAVA.equals(element)) { + String packageName = reader.getAttributeValue(null, PACKAGE); + if (packageName == null) { + error(context.getMonitor(), "AttributePackageMissing", reader); + //throw new ContributionReadException("Attribute 'package' is missing"); + } else + javaImport.setPackage(packageName); + + String location = getURIString(reader, LOCATION); + javaImport.setLocation(location); + } + break; + case XMLStreamConstants.END_ELEMENT: + if (IMPORT_JAVA.equals(reader.getName())) { + return javaImport; + } + break; + } + + // Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + } + catch (XMLStreamException e) { + ContributionReadException ex = new ContributionReadException(e); + error(context.getMonitor(), "XMLStreamException", reader, ex); + } + + return javaImport; + } + + public void write(JavaImport javaImport, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException { + + // Write <import.java> + writer.writeStartElement(IMPORT_JAVA.getNamespaceURI(), IMPORT_JAVA.getLocalPart()); + + if (javaImport.getPackage() != null) { + writer.writeAttribute(PACKAGE, javaImport.getPackage()); + } + if (javaImport.getLocation() != null) { + writer.writeAttribute(LOCATION, javaImport.getLocation()); + } + + writer.writeEndElement(); + } + + + public void resolve(JavaImport model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java new file mode 100644 index 0000000000..a71fa61a54 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace; + +import org.apache.tuscany.sca.contribution.namespace.impl.NamespaceImportExportFactoryImpl; + +/** + * Default Namespace Import/Export model factory implementation + * + * @version $Rev$ $Date$ + */ +public class DefaultNamespaceImportExportFactory extends NamespaceImportExportFactoryImpl implements NamespaceImportExportFactory { +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java new file mode 100644 index 0000000000..c68aee8521 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace; + +import org.apache.tuscany.sca.contribution.Export; + + +/** + * The representation of an XML namespace export. + * + * @version $Rev$ $Date$ + */ +public interface NamespaceExport extends Export { + + /** + * Get Namespace that identifies the export + * + * @return The exported namespace + */ + String getNamespace(); + + /** + * Set Namespace that identifies the export + * + * @param namespace The exported namespace + */ + void setNamespace(String namespace); + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java new file mode 100644 index 0000000000..c452b15ee9 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace; + +import org.apache.tuscany.sca.contribution.Import; + +/** + * The representation of an XML namespace import. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface NamespaceImport extends Import { + + /** + * Get the location used to resolve the definitions for this import + * + * @return The import location + */ + String getLocation(); + + /** + * Set the location used to resolve the definitions for this import + * + * @param location The import location + */ + void setLocation(String location); + + /** + * Get Namespace that identifies the import + * + * @return The namespace + */ + String getNamespace(); + + /** + * Set Namespace that identifies the import + * + * @param namespace The namespace + */ + void setNamespace(String namespace); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java new file mode 100644 index 0000000000..cfbac8bb1f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace; + +/** + * Base Namespace import/export model factory + * + * @version $Rev$ $Date$ + */ +public interface NamespaceImportExportFactory { + + /** + * Create a namespace import model object + * + * @return The new NamespaceImport model object + */ + NamespaceImport createNamespaceImport(); + + /** + * Create a namespace export model object + * + * @return The new NamespaceExport model object + */ + NamespaceExport createNamespaceExport(); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java new file mode 100644 index 0000000000..99af328964 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace.impl; + +import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl; +import org.apache.tuscany.sca.contribution.namespace.NamespaceExport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of an export for the contribution + * + * @version $Rev$ $Date$ + */ +public class NamespaceExportImpl extends ExtensibleImpl implements NamespaceExport { + private String namespace; + private ModelResolver modelResolver; + + protected NamespaceExportImpl() { + super(); + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java new file mode 100644 index 0000000000..7bf3c32c93 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace.impl; + +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * A model resolver for namespace exports. + * + * @version $Rev$ $Date$ + */ +public class NamespaceExportModelResolver implements ModelResolver { + + private ModelResolver resolver; + + public NamespaceExportModelResolver(ModelResolver resolver) { + this.resolver = resolver; + } + + public void addModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + + // Just delegate to the contribution's model resolver, namespace + // based filtering is implemented in the model specific model + // resolver, which know how to get the namespace of the particular + // type of model that they handle + return resolver.resolveModel(modelClass, unresolved, context); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java new file mode 100644 index 0000000000..0d410fb377 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java @@ -0,0 +1,172 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace.impl; + +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.contribution.namespace.NamespaceExport; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Artifact processor for Namespace export + * + * @version $Rev$ $Date$ + */ +public class NamespaceExportProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor<NamespaceExport> { + + private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200912"; + private static final QName EXPORT = new QName(SCA11_NS, "export"); + private static final String NAMESPACE = "namespace"; + + private final NamespaceImportExportFactory factory; + private final AssemblyFactory extensionFactory; + private final StAXArtifactProcessor<Object> extensionProcessor; + private final StAXAttributeProcessor<Object> attributeProcessor; + + public NamespaceExportProcessor(FactoryExtensionPoint modelFactories, + StAXArtifactProcessor<Object> extensionProcessor, + StAXAttributeProcessor<Object> attributeProcessor) { + this.factory = modelFactories.getFactory(NamespaceImportExportFactory.class); + this.extensionFactory = modelFactories.getFactory(AssemblyFactory.class); + this.extensionProcessor = extensionProcessor; + this.attributeProcessor = attributeProcessor; + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-namespace-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + public QName getArtifactType() { + return EXPORT; + } + + public Class<NamespaceExport> getModelType() { + return NamespaceExport.class; + } + + /** + * Process <export namespace=""/> + */ + public NamespaceExport read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException { + NamespaceExport namespaceExport = this.factory.createNamespaceExport(); + QName element = null; + + try { + while (reader.hasNext()) { + int event = reader.getEventType(); + switch (event) { + case START_ELEMENT: + element = reader.getName(); + + // Read <export> + if (EXPORT.equals(element)) { + String ns = reader.getAttributeValue(null, NAMESPACE); + if (ns == null) { + error(context.getMonitor(), "AttributeNameSpaceMissing", reader); + //throw new ContributionReadException("Attribute 'namespace' is missing"); + } else { + namespaceExport.setNamespace(ns); + } + readExtendedAttributes(reader, namespaceExport, attributeProcessor, extensionFactory, context); + } else { + //read extended elements + Object ext = extensionProcessor.read(reader, context); + if (namespaceExport != null) { + namespaceExport.getExtensions().add(ext); + } + } + + break; + case XMLStreamConstants.END_ELEMENT: + if (EXPORT.equals(reader.getName())) { + return namespaceExport; + } + break; + } + + // Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + } + catch (XMLStreamException e) { + ContributionReadException ex = new ContributionReadException(e); + error(context.getMonitor(), "XMLStreamException", reader, ex); + } + + return namespaceExport; + } + + public void write(NamespaceExport namespaceExport, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException { + + // Write <export> + writer.writeStartElement(EXPORT.getNamespaceURI(), EXPORT.getLocalPart()); + + if (namespaceExport.getNamespace() != null) { + writer.writeAttribute(NAMESPACE, namespaceExport.getNamespace()); + } + + writeExtendedAttributes(writer, namespaceExport, attributeProcessor, context); + + // handle extended elements + for (Object ext : namespaceExport.getExtensions()) { + extensionProcessor.write(ext, writer, context); + } + + writer.writeEndElement(); + } + + public void resolve(NamespaceExport namespaceExport, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + + if (namespaceExport.getNamespace() != null) + // Initialize the export's resolver + namespaceExport.setModelResolver(new NamespaceExportModelResolver(resolver)); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java new file mode 100644 index 0000000000..1146e593a9 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace.impl; + +import org.apache.tuscany.sca.contribution.namespace.NamespaceExport; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImport; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory; + +/** + * Namespace Import/Export model factory implementation + * + * @version $Rev$ $Date$ + */ +public class NamespaceImportExportFactoryImpl implements NamespaceImportExportFactory { + + public NamespaceImport createNamespaceImport() { + return new NamespaceImportImpl(); + } + + public NamespaceExport createNamespaceExport() { + return new NamespaceExportImpl(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java new file mode 100644 index 0000000000..35e2d539d4 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace.impl; + +import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.namespace.NamespaceExport; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of an import for the contribution + * + * @version $Rev$ $Date$ + */ +public class NamespaceImportImpl extends ExtensibleImpl implements NamespaceImport { + private ModelResolver modelResolver; + + /** + * The namespace to be imported + */ + private String namespace; + /** + * Optional location URI pointing to a Contribution that exports the namespace + */ + private String location; + + + protected NamespaceImportImpl() { + super(); + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + + + /** + * Match a NamespaceImport to a given NamespaceExport based on : + * location is not provided + * import and export namespaces match + */ + public boolean match(Export export) { + if (export instanceof NamespaceExport) { + if (this.getNamespace().equals(((NamespaceExport)export).getNamespace())) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return String.valueOf(namespace); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java new file mode 100644 index 0000000000..17b0dc3953 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java @@ -0,0 +1,178 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.namespace.impl; + +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImport; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Artifact processor for Namespace import + * + * @version $Rev$ $Date$ + */ +public class NamespaceImportProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor<NamespaceImport> { + private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200912"; + + private static final QName IMPORT = new QName(SCA11_NS, "import"); + + private static final String NAMESPACE = "namespace"; + private static final String LOCATION = "location"; + + private final NamespaceImportExportFactory factory; + private final AssemblyFactory extensionFactory; + private final StAXArtifactProcessor<Object> extensionProcessor; + private final StAXAttributeProcessor<Object> attributeProcessor; + + public NamespaceImportProcessor(FactoryExtensionPoint modelFactories, + StAXArtifactProcessor<Object> extensionProcessor, + StAXAttributeProcessor<Object> attributeProcessor) { + this.factory = modelFactories.getFactory(NamespaceImportExportFactory.class); + this.extensionFactory = modelFactories.getFactory(AssemblyFactory.class); + this.extensionProcessor = extensionProcessor; + this.attributeProcessor = attributeProcessor; + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-namespace-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + public QName getArtifactType() { + return IMPORT; + } + + public Class<NamespaceImport> getModelType() { + return NamespaceImport.class; + } + + /** + * Process <import namespace="" location=""/> + */ + public NamespaceImport read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException { + NamespaceImport namespaceImport = this.factory.createNamespaceImport(); + QName element; + + try { + while (reader.hasNext()) { + int event = reader.getEventType(); + switch (event) { + case START_ELEMENT: + element = reader.getName(); + + // Read <import> + if (IMPORT.equals(element)) { + String ns = reader.getAttributeValue(null, NAMESPACE); + if (ns == null) { + error(context.getMonitor(), "AttributeNameSpaceMissing", reader); + //throw new ContributionReadException("Attribute 'namespace' is missing"); + } else { + namespaceImport.setNamespace(ns); + } + + String location = getURIString(reader, LOCATION); + if (location != null) { + namespaceImport.setLocation(location); + } + readExtendedAttributes(reader, namespaceImport, attributeProcessor, extensionFactory, context); + } else { + // handle extended elements + Object ext = extensionProcessor.read(reader, context); + if (namespaceImport != null) { + namespaceImport.getExtensions().add(ext); + } + } + break; + case XMLStreamConstants.END_ELEMENT: + if (IMPORT.equals(reader.getName())) { + return namespaceImport; + } + break; + } + + // Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + } + catch (XMLStreamException e) { + ContributionReadException ex = new ContributionReadException(e); + error(context.getMonitor(), "XMLStreamException", reader, ex); + } + + return namespaceImport; + } + + public void write(NamespaceImport namespaceImport, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException { + + // Write <import> + writer.writeStartElement(IMPORT.getNamespaceURI(), IMPORT.getLocalPart()); + + if (namespaceImport.getNamespace() != null) { + writer.writeAttribute(NAMESPACE, namespaceImport.getNamespace()); + } + if (namespaceImport.getLocation() != null) { + writer.writeAttribute(LOCATION, namespaceImport.getLocation()); + } + + writeExtendedAttributes(writer, namespaceImport, attributeProcessor, context); + + //handle extended elements + for (Object ext : namespaceImport.getExtensions()) { + extensionProcessor.write(ext, writer, context); + } + + writer.writeEndElement(); + } + + + public void resolve(NamespaceImport model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java new file mode 100644 index 0000000000..9ac3aebaf6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java @@ -0,0 +1,48 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * Base interface for artifact processors. + * + * @version $Rev$ $Date$ + */ +public interface ArtifactProcessor<M> { + + /** + * Resolve references from this model to other models. For example references + * from a composite to another one, or references from a composite to a WSDL + * model. + * + * @param model The model to resolve + * @param resolver The resolver to use to resolve referenced models + * @param context The context for the processor + */ + void resolve(M model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException; + + /** + * Returns the type of model handled by this artifact processor. + * + * @return The type of model handled by this artifact processor + */ + Class<M> getModelType(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java new file mode 100644 index 0000000000..82902a11fe --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java @@ -0,0 +1,532 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Extensible; +import org.apache.tuscany.sca.assembly.Extension; +import org.apache.tuscany.sca.common.xml.stax.StAXHelper; + + +/** + * A base class with utility methods for the other artifact processors in this module. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public abstract class BaseStAXArtifactProcessor { + private static String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200912"; + private static String SCA11_TUSCANY_NS = "http://tuscany.apache.org/xmlns/sca/1.1"; + + /** + * The StAXHelper without states + */ + private static final StAXHelper helper = new StAXHelper(null, null, null); + /** + * Returns a QName from a string. + * @param reader + * @param value + * @return + */ + protected QName getQNameValue(XMLStreamReader reader, String value) { + return StAXHelper.getValueAsQName(reader, value); + } + + /** + * Returns the boolean value of an attribute. + * @param reader + * @param name + * @return + */ + protected boolean getBoolean(XMLStreamReader reader, String name) { + Boolean attr = StAXHelper.getAttributeAsBoolean(reader, name); + if (attr == null) { + return false; + } else { + return attr.booleanValue(); + } + } + + /** + * Returns the QName value of an attribute. + * @param reader + * @param name + * @return + */ + protected QName getQName(XMLStreamReader reader, String name) { + return StAXHelper.getAttributeAsQName(reader, name); + } + + /** + * Returns the value of an attribute as a list of QNames. + * @param reader + * @param name + * @return + */ + protected List<QName> getQNames(XMLStreamReader reader, String name) { + return StAXHelper.getAttributeAsQNames(reader, name); + } + + /** + * Returns the string value of an attribute. + * @param reader + * @param name + * @return + */ + protected String getString(XMLStreamReader reader, String name) { + return StAXHelper.getAttributeAsString(reader, name); + } + + /** + * Returns the string value of an attribute. + * @param reader + * @param name + * @return + */ + protected String getURIString(XMLStreamReader reader, String name) { + return StAXHelper.getAttributeAsURIString(reader, name); + } + + /** + * Test if an attribute is explicitly set + * @param reader + * @param name + * @return + */ + protected boolean isSet(XMLStreamReader reader, String name) { + return StAXHelper.isAttributePresent(reader, name); + } + + /** + * Returns the value of xsi:type attribute + * @param reader The XML stream reader + * @return The QName of the type, if the attribute is not present, null is + * returned. + */ + protected QName getXSIType(XMLStreamReader reader) { + return StAXHelper.getXSIType(reader); + } + + /** + * Parse the next child element. + * @param reader + * @return + * @throws XMLStreamException + */ + protected boolean nextChildElement(XMLStreamReader reader) throws XMLStreamException { + while (reader.hasNext()) { + int event = reader.next(); + if (event == END_ELEMENT) { + return false; + } + if (event == START_ELEMENT) { + return true; + } + } + return false; + } + + /** + * Advance the stream to the next END_ELEMENT event skipping any nested + * content. + * @param reader the reader to advance + * @throws XMLStreamException if there was a problem reading the stream + */ + protected void skipToEndElement(XMLStreamReader reader) throws XMLStreamException { + StAXHelper.skipToEndElement(reader); + } + + /** + * + * @param writer + * @param uri + * @throws XMLStreamException + */ + private String setPrefix(XMLStreamWriter writer, String uri) throws XMLStreamException { + if (uri == null) { + return null; + } + String prefix = writer.getPrefix(uri); + if (prefix != null) { + return null; + } else { + + // Find an available prefix and bind it to the given URI + NamespaceContext nsc = writer.getNamespaceContext(); + for (int i=1; ; i++) { + prefix = "ns" + i; + if (nsc.getNamespaceURI(prefix) == null) { + break; + } + } + writer.setPrefix(prefix, uri); + return prefix; + } + + } + + /** + * Start an element. + * @param uri + * @param name + * @param attrs + * @throws XMLStreamException + */ + protected void writeStart(XMLStreamWriter writer, String uri, String name, XAttr... attrs) + throws XMLStreamException { + helper.writeStartElement(writer, "", name, uri); + writeAttributes(writer, attrs); + } + + /** + * Start an element. + * @param qname + * @param attrs + * @throws XMLStreamException + */ + protected void writeStart(XMLStreamWriter writer, QName qname, XAttr... attrs) throws XMLStreamException { + writeStart(writer, qname.getNamespaceURI(), qname.getLocalPart(), attrs); + } + + /** + * End an element. + * @param writer + * @throws XMLStreamException + */ + protected void writeEnd(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndElement(); + } + + /** + * Start a document. + * @param writer + * @throws XMLStreamException + */ + protected void writeStartDocument(XMLStreamWriter writer, String uri, String name, XAttr... attrs) throws XMLStreamException { + writer.writeStartDocument(); + writer.setDefaultNamespace(uri); + writeStart(writer, uri, name, attrs); + // writer.writeDefaultNamespace(uri); + } + + /** + * Start a document. + * @param writer + * @param qname + * @param attrs + * @throws XMLStreamException + */ + protected void writeStartDocument(XMLStreamWriter writer, QName qname, XAttr... attrs) throws XMLStreamException { + writeStartDocument(writer, qname.getNamespaceURI(), qname.getLocalPart(), attrs); + } + + /** + * End a document. + * @param writer + * @throws XMLStreamException + */ + protected void writeEndDocument(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndDocument(); + } + + /** + * Write attributes to the current element. + * @param writer + * @param attrs + * @throws XMLStreamException + */ + protected void writeAttributes(XMLStreamWriter writer, XAttr... attrs) throws XMLStreamException { + for (XAttr attr : attrs) { + if (attr != null) + attr.write(writer); + } + } + + /** + * + * @param reader + * @param extensible + * @param extensionAttributeProcessor + * @param extensionAttributeProcessor + * @param extensionFactory + * @param context TODO + * @param elementName + * @throws ContributionReadException + * @throws XMLStreamException + */ + protected void readExtendedAttributes(XMLStreamReader reader, + Extensible extensible, + StAXAttributeProcessor extensionAttributeProcessor, + AssemblyFactory extensionFactory, ProcessorContext context) throws ContributionReadException, + XMLStreamException { + QName elementName = reader.getName(); + for (int a = 0; a < reader.getAttributeCount(); a++) { + QName attributeName = reader.getAttributeName(a); + if (attributeName.getNamespaceURI() != null && attributeName.getNamespaceURI().length() > 0) { + if (!elementName.getNamespaceURI().equals(attributeName.getNamespaceURI())) { + Object attributeValue = extensionAttributeProcessor.read(attributeName, reader, context); + Extension attributeExtension; + if (attributeValue instanceof Extension) { + attributeExtension = (Extension)attributeValue; + } else { + attributeExtension = extensionFactory.createExtension(); + attributeExtension.setQName(attributeName); + attributeExtension.setValue(attributeValue); + attributeExtension.setAttribute(true); + } + extensible.getAttributeExtensions().add(attributeExtension); + } + } + } + } + + /** + * + * @param writer + * @param extensibleElement + * @param extensionAttributeProcessor + * @param context TODO + * @param attributeModel + * @throws ContributionWriteException + * @throws XMLStreamException + */ + protected void writeExtendedAttributes(XMLStreamWriter writer, + Extensible extensibleElement, + StAXAttributeProcessor extensionAttributeProcessor, ProcessorContext context) + throws ContributionWriteException, XMLStreamException { + + for (Extension extension : extensibleElement.getAttributeExtensions()) { + if (extension.isAttribute()) { + extensionAttributeProcessor.write(extension, writer, context); + } + } + } + + protected void readExtendedElement(XMLStreamReader reader, + Extensible extensible, + StAXArtifactProcessor extensionProcessor, ProcessorContext context) + throws ContributionReadException, XMLStreamException { + + Object ext = extensionProcessor.read(reader, context); + if (extensible != null) { + extensible.getExtensions().add(ext); + } + } + + protected void writeExtendedElements(XMLStreamWriter writer, + Extensible extensible, + StAXArtifactProcessor extensionProcessor, ProcessorContext context) + throws ContributionWriteException, XMLStreamException { + + List <Object> otherExtensions = new ArrayList<Object>(); + + // write all generic extensions as elements + // to produce semanticaly equal xml output + for (Object ext : extensible.getExtensions()) { + if (ext instanceof Extension) { + extensionProcessor.write(ext, writer, context); + } else { + otherExtensions.add(ext); + } + } + + //wrap xml extensibility into a extension wrapper element + if(otherExtensions.size() > 0) { + + writeStart(writer, SCA11_NS, "extensions"); + + for (Object extension : otherExtensions) { + extensionProcessor.write(extension, writer, context); + } + + writeEnd(writer); + } + + } + + /** + * Represents an XML attribute that needs to be written to a document. + */ + public static class XAttr { + + private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200912"; + + private String uri = SCA11_NS; + private String name; + private Object value; + + public XAttr(String uri, String name, String value) { + this.uri = uri; + this.name = name; + this.value = value; + } + + public XAttr(String name, String value) { + this(null, name, value); + } + + public XAttr(String uri, String name, List<?> values) { + this.uri = uri; + this.name = name; + this.value = values; + } + + public XAttr(String name, List<?> values) { + this(null, name, values); + } + + public XAttr(String uri, String name, Boolean value) { + this.uri = uri; + this.name = name; + this.value = value; + } + + public XAttr(String name, Boolean value) { + this(null, name, value); + } + + public XAttr(String uri, String name, Integer value) { + this.uri = uri; + this.name = name; + this.value = value; + } + + public XAttr(String name, Integer value) { + this(null, name, value); + } + + public XAttr(String uri, String name, Double value) { + this.uri = uri; + this.name = name; + this.value = value; + } + + public XAttr(String name, Double value) { + this(null, name, value); + } + + public XAttr(String uri, String name, QName value) { + this.uri = uri; + this.name = name; + this.value = value; + } + + public XAttr(String name, QName value) { + this(null, name, value); + } + + public String toString() { + return uri == null ? name + "=\"" + value + "\"" : "{" + uri + "}" + name + "=\"" + value + "\""; + } + + /** + * Writes a string from a QName and registers a prefix for its namespace. + * @param reader + * @param value + * @return + */ + private String writeQNameValue(XMLStreamWriter writer, QName qname) throws XMLStreamException { + if (qname != null) { + String prefix = helper.writeNamespace(writer, qname.getPrefix(), qname.getNamespaceURI()); + if ("".equals(prefix)) { + return qname.getLocalPart(); + } else { + return prefix + ":" + qname.getLocalPart(); + } + } + return null; + } + + /** + * Write to document + * @param writer + * @throws XMLStreamException + */ + public void write(XMLStreamWriter writer) throws XMLStreamException { + String str; + if (value instanceof QName) { + + // Write a QName + str = writeQNameValue(writer, (QName)value); + + } else if (value instanceof Collection) { + + // Write a list of values + Collection<?> values = (Collection<?>)value; + if (values.isEmpty()) { + return; + } + StringBuffer buffer = new StringBuffer(); + for (Object v: values) { + if (v == null) { + // Skip null values + continue; + } + + if (v instanceof XAttr) { + // Write an XAttr value + ((XAttr)v).write(writer); + continue; + } + + if (buffer.length() != 0) { + buffer.append(' '); + } + if (v instanceof QName) { + // Write a QName value + buffer.append(writeQNameValue(writer, (QName)v)); + } else { + // Write value as a string + buffer.append(String.valueOf(v)); + } + } + str = buffer.toString(); + + } else { + + // Write a string + if (value == null) { + return; + } + str = String.valueOf(value); + } + if (str.length() == 0 && (value instanceof Collection)) { + return; + } + + helper.writeAttribute(writer, "", name, uri, str); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java new file mode 100644 index 0000000000..93cb8c7fc7 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java @@ -0,0 +1,46 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +/** + * Base class for exceptions raised by contribution services. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class ContributionException extends Exception { + + private static final long serialVersionUID = 4432880414927652578L; + + protected ContributionException() { + super(); + } + + protected ContributionException(String message) { + super(message); + } + + protected ContributionException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java new file mode 100644 index 0000000000..ced2ad1899 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java @@ -0,0 +1,96 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + + +/** + * Denotes an exception while reading artifacts inside an SCA contribution. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class ContributionReadException extends ContributionException { + public static final int UNDEFINED = -1; + private static final long serialVersionUID = -7459051598906813461L; + private String resourceURI; + private int line = UNDEFINED; + private int column = UNDEFINED; + + public ContributionReadException(String message) { + super(message); + } + + public ContributionReadException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionReadException(Throwable cause) { + super(cause); + } + + /** + * Returns the location of the resource that was being read. + * + * @return the location of the resource that was being read + */ + public String getResourceURI() { + return resourceURI; + } + + /** + * Sets the location of the resource that was being read. + * + * @param resourceURI the location of the resource that was being read + */ + public void setResourceURI(String resourceURI) { + this.resourceURI = resourceURI; + } + + /** + * Returns the line inside the resource that was being read. + * @return the line inside the resource that was being read + */ + public int getLine() { + return line; + } + + /** + * Sets the line inside the resource that was being read. + * @param line the line inside the resource that was being read + */ + public void setLine(int line) { + this.line = line; + } + + /** + * Returns the column inside the resource that was being read. + * @return the column inside the resource that was being read + */ + public int getColumn() { + return column; + } + + /** + * Sets the column inside the resource that was being read. + * @param column the column inside the resource that was being read + */ + public void setColumn(int column) { + this.column = column; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java new file mode 100644 index 0000000000..af42c25734 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java @@ -0,0 +1,43 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + + +/** + * Denotes a problem while resolving models inside an SCA contribution. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class ContributionResolveException extends ContributionException { + private static final long serialVersionUID = -7459051598906813461L; + + public ContributionResolveException(String message) { + super(message); + } + + public ContributionResolveException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionResolveException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java new file mode 100644 index 0000000000..9db6292e3d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java @@ -0,0 +1,45 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +/** + * Base class for runtime exceptions raised by contribution services. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class ContributionRuntimeException extends RuntimeException { + private static final long serialVersionUID = 7711215366287498896L; + + protected ContributionRuntimeException() { + super(); + } + + protected ContributionRuntimeException(String message) { + super(message); + } + + protected ContributionRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionRuntimeException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java new file mode 100644 index 0000000000..4e1cd287bb --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java @@ -0,0 +1,63 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + + + +/** + * Denotes an exception while writing artifacts inside an SCA contribution. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class ContributionWriteException extends ContributionException { + private static final long serialVersionUID = -7459051598906813461L; + private String resourceURI; + + public ContributionWriteException(String message) { + super(message); + } + + public ContributionWriteException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionWriteException(Throwable cause) { + super(cause); + } + + /** + * Returns the location of the resource that was being written. + * + * @return the location of the resource that was being written + */ + public String getResourceURI() { + return resourceURI; + } + + /** + * Sets the location of the resource that was being written. + * + * @param resourceURI the location of the resource that was being written + */ + public void setResourceURI(String resourceURI) { + this.resourceURI = resourceURI; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..c871e4c868 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java @@ -0,0 +1,66 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.util.HashMap; +import java.util.Map; + +/** + * The default implementation of an artifact processor extension point. + * + * @version $Rev$ $Date$ + */ +abstract class DefaultArtifactProcessorExtensionPoint<P extends ArtifactProcessor<?>> { + protected final Map<Object, P> processorsByArtifactType = new HashMap<Object, P>(); + protected final Map<Class<?>, P> processorsByModelType = new HashMap<Class<?>, P>(); + + /** + * Constructs a new loader registry. + */ + DefaultArtifactProcessorExtensionPoint() { + } + + /** + * Returns the processor associated with the given artifact type. + * + * @param artifactType An artifact type + * @return The processor associated with the given artifact type + */ + public P getProcessor(Object artifactType) { + return processorsByArtifactType.get(artifactType); + } + + /** + * Returns the processor associated with the given model type. + * + * @param modelType A model type + * @return The processor associated with the given model type + */ + public <T> P getProcessor(Class<T> modelType) { + Class<?>[] classes = modelType.getInterfaces(); + for (Class<?> c : classes) { + P processor = processorsByModelType.get(c); + if (processor != null) { + return processor; + } + } + return processorsByModelType.get(modelType); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..151edeae0b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java @@ -0,0 +1,325 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDeclarationParser; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * The default implementation of an extension point for StAX artifact processors. + * + * @version $Rev$ $Date$ + */ +public class DefaultStAXArtifactProcessorExtensionPoint extends + DefaultArtifactProcessorExtensionPoint<StAXArtifactProcessor<?>> implements StAXArtifactProcessorExtensionPoint { + + private ExtensionPointRegistry registry; + private FactoryExtensionPoint modelFactories; + private boolean loaded; + private StAXArtifactProcessor<Object> extensibleStAXProcessor; + private StAXAttributeProcessor<Object> extensibleStAXAttributeProcessor; + + /** + * Constructs a new extension point. + */ + public DefaultStAXArtifactProcessorExtensionPoint(ExtensionPointRegistry extensionPoints) { + this.registry = extensionPoints; + this.modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + XMLInputFactory inputFactory = modelFactories.getFactory(XMLInputFactory.class); + XMLOutputFactory outputFactory = modelFactories.getFactory(XMLOutputFactory.class); + this.extensibleStAXProcessor = new ExtensibleStAXArtifactProcessor(this, inputFactory, outputFactory); + + StAXAttributeProcessorExtensionPoint attributeExtensionPoint = + extensionPoints.getExtensionPoint(StAXAttributeProcessorExtensionPoint.class); + this.extensibleStAXAttributeProcessor = + new ExtensibleStAXAttributeProcessor(attributeExtensionPoint, inputFactory, outputFactory); + } + + public void addArtifactProcessor(StAXArtifactProcessor<?> artifactProcessor) { + if (artifactProcessor.getArtifactType() != null) { + processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor); + } + if (artifactProcessor.getModelType() != null) { + processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor); + } + } + + public void removeArtifactProcessor(StAXArtifactProcessor<?> artifactProcessor) { + if (artifactProcessor.getArtifactType() != null) { + processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType()); + } + if (artifactProcessor.getModelType() != null) { + processorsByModelType.remove(artifactProcessor.getModelType()); + } + } + + @Override + public <T> StAXArtifactProcessor<T> getProcessor(Class<T> modelType) { + loadArtifactProcessors(); + return (StAXArtifactProcessor<T>)super.getProcessor(modelType); + } + + @Override + public StAXArtifactProcessor<?> getProcessor(Object artifactType) { + loadArtifactProcessors(); + return super.getProcessor(artifactType); + } + + /** + * Lazily load artifact processors registered in the extension point. + */ + private synchronized void loadArtifactProcessors() { + if (loaded) + return; + + // Get the processor service declarations + Collection<ServiceDeclaration> processorDeclarations; + try { + processorDeclarations = + registry.getServiceDiscovery().getServiceDeclarations(StAXArtifactProcessor.class.getName()); + } catch (IOException e) { + IllegalStateException ie = new IllegalStateException(e); + throw ie; + } + + for (ServiceDeclaration processorDeclaration : processorDeclarations) { + Map<String, String> attributes = processorDeclaration.getAttributes(); + + // Load a StAX artifact processor + + // Get the model QName + QName artifactType = ServiceDeclarationParser.getQName(attributes.get("qname")); + + // Get the model class name + String modelTypeName = attributes.get("model"); + + // Get the model factory class name + String factoryName = attributes.get("factory"); + + // Create a processor wrapper and register it + StAXArtifactProcessor<?> processor = + new LazyStAXArtifactProcessor(artifactType, modelTypeName, factoryName, processorDeclaration, + registry, modelFactories, extensibleStAXProcessor, + extensibleStAXAttributeProcessor); + addArtifactProcessor(processor); + } + + loaded = true; + } + + /** + * A wrapper around an Artifact processor class allowing lazy loading and + * initialization of artifact processors. + */ + private static class LazyStAXArtifactProcessor implements StAXArtifactProcessor { + + private ExtensionPointRegistry extensionPoints; + private QName artifactType; + private String modelTypeName; + private String factoryName; + private ServiceDeclaration processorDeclaration; + private StAXArtifactProcessor<?> processor; + private Class<?> modelType; + private StAXArtifactProcessor<Object> extensionProcessor; + private StAXAttributeProcessor<Object> extensionAttributeProcessor; + + LazyStAXArtifactProcessor(QName artifactType, + String modelTypeName, + String factoryName, + ServiceDeclaration processorDeclaration, + ExtensionPointRegistry extensionPoints, + FactoryExtensionPoint modelFactories, + StAXArtifactProcessor<Object> extensionProcessor, + StAXAttributeProcessor<Object> extensionAttributeProcessor) { + + this.extensionPoints = extensionPoints; + this.artifactType = artifactType; + this.modelTypeName = modelTypeName; + this.factoryName = factoryName; + this.processorDeclaration = processorDeclaration; + this.extensionProcessor = extensionProcessor; + this.extensionAttributeProcessor = extensionAttributeProcessor; + } + + public QName getArtifactType() { + return artifactType; + } + + private void error(Monitor monitor, String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.ERROR, + model, + message, + ex); + monitor.problem(problem); + } + } + + @SuppressWarnings("unchecked") + private StAXArtifactProcessor getProcessor() { + if (processor == null) { + + if (processorDeclaration.getClassName() + .equals("org.apache.tuscany.sca.assembly.xml.DefaultBeanModelProcessor")) { + + // Specific initialization for the DefaultBeanModelProcessor + FactoryExtensionPoint modelFactories = + extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + try { + Class<StAXArtifactProcessor> processorClass = + (Class<StAXArtifactProcessor>)processorDeclaration.loadClass(); + Object modelFactory; + if (factoryName != null) { + Class<?> factoryClass = (Class<?>)processorDeclaration.loadClass(factoryName); + modelFactory = modelFactories.getFactory(factoryClass); + } else { + modelFactory = null; + } + Constructor<StAXArtifactProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class, + QName.class, + Class.class, + Object.class); + processor = constructor.newInstance(modelFactories, artifactType, getModelType(), modelFactory); + } catch (Exception e) { + IllegalStateException ie = new IllegalStateException(e); + throw ie; + } + } else { + FactoryExtensionPoint modelFactories = + extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + + // Load and instantiate the processor class + try { + Class<StAXArtifactProcessor> processorClass = + (Class<StAXArtifactProcessor>)processorDeclaration.loadClass(); + try { + Constructor<StAXArtifactProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class); + processor = constructor.newInstance(modelFactories); + } catch (NoSuchMethodException e) { + try { + Constructor<StAXArtifactProcessor> constructor = + processorClass.getConstructor(ExtensionPointRegistry.class); + processor = constructor.newInstance(extensionPoints); + } catch (NoSuchMethodException e1) { + try { + Constructor<StAXArtifactProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class, + StAXArtifactProcessor.class); + processor = constructor.newInstance(modelFactories, extensionProcessor); + } catch (NoSuchMethodException e2) { + try { + Constructor<StAXArtifactProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class, + StAXArtifactProcessor.class, + StAXAttributeProcessor.class); + processor = + constructor.newInstance(modelFactories, + extensionProcessor, + extensionAttributeProcessor); + } catch (NoSuchMethodException e2a) { + try { + Constructor<StAXArtifactProcessor> constructor = + processorClass.getConstructor(ExtensionPointRegistry.class, + StAXArtifactProcessor.class); + processor = constructor.newInstance(extensionPoints, extensionProcessor); + } catch (NoSuchMethodException e3) { + try { + Constructor<StAXArtifactProcessor> constructor = + processorClass.getConstructor(ExtensionPointRegistry.class, + StAXArtifactProcessor.class, + StAXAttributeProcessor.class); + processor = + constructor.newInstance(extensionPoints, + extensionProcessor, + extensionAttributeProcessor); + } catch (NoSuchMethodException e3a) { + + Constructor<StAXArtifactProcessor> constructor = + processorClass.getConstructor(); + processor = constructor.newInstance(); + + } + } + } + } + } + } + } catch (Exception e) { + IllegalStateException ie = new IllegalStateException(e); + throw ie; + } + } + } + return processor; + } + + public Object read(XMLStreamReader inputSource, ProcessorContext context) throws ContributionReadException, + XMLStreamException { + return getProcessor().read(inputSource, context); + } + + @SuppressWarnings("unchecked") + public void write(Object model, XMLStreamWriter outputSource, ProcessorContext context) + throws ContributionWriteException, XMLStreamException { + getProcessor().write(model, outputSource, context); + } + + public Class<?> getModelType() { + if (modelTypeName != null && modelType == null) { + try { + modelType = processorDeclaration.loadClass(modelTypeName); + } catch (Exception e) { + IllegalStateException ie = new IllegalStateException(e); + throw ie; + } + } + return modelType; + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver, ProcessorContext context) + throws ContributionResolveException { + getProcessor().resolve(model, resolver, context); + } + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java new file mode 100644 index 0000000000..e76d6cb299 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java @@ -0,0 +1,292 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDeclarationParser; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.MonitorFactory; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * The default implementation of an extension point for StAX artifact processors. + * + * @version $Rev$ $Date$ + */ +public class DefaultStAXAttributeProcessorExtensionPoint extends + DefaultArtifactProcessorExtensionPoint<StAXAttributeProcessor<?>> implements StAXAttributeProcessorExtensionPoint { + + private ExtensionPointRegistry registry; + private FactoryExtensionPoint modelFactories; + private StAXAttributeProcessor<Object> extensibleStAXAttributeProcessor; + private boolean loaded; + private Monitor monitor = null; + + /** + * Constructs a new extension point. + */ + public DefaultStAXAttributeProcessorExtensionPoint(ExtensionPointRegistry extensionPoints) { + this.registry = extensionPoints; + this.modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + XMLInputFactory inputFactory = modelFactories.getFactory(XMLInputFactory.class); + XMLOutputFactory outputFactory = modelFactories.getFactory(XMLOutputFactory.class); + UtilityExtensionPoint utilities = this.registry.getExtensionPoint(UtilityExtensionPoint.class); + MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class); + if (monitorFactory != null) { + this.monitor = monitorFactory.createMonitor(); + } + this.extensibleStAXAttributeProcessor = new ExtensibleStAXAttributeProcessor(this, inputFactory, outputFactory); + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.ERROR, + model, + message, + ex); + monitor.problem(problem); + } + } + + public void addArtifactProcessor(StAXAttributeProcessor<?> artifactProcessor) { + if (artifactProcessor.getArtifactType() != null) { + processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor); + } + if (artifactProcessor.getModelType() != null) { + processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor); + } + } + + public void removeArtifactProcessor(StAXAttributeProcessor<?> artifactProcessor) { + if (artifactProcessor.getArtifactType() != null) { + processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType()); + } + if (artifactProcessor.getModelType() != null) { + processorsByModelType.remove(artifactProcessor.getModelType()); + } + } + + @Override + public <T> StAXAttributeProcessor<T> getProcessor(Class<T> modelType) { + loadArtifactProcessors(); + return (StAXAttributeProcessor<T>)super.getProcessor(modelType); + } + + @Override + public StAXAttributeProcessor<?> getProcessor(Object artifactType) { + loadArtifactProcessors(); + return super.getProcessor(artifactType); + } + + /** + * Lazily load artifact processors registered in the extension point. + */ + private synchronized void loadArtifactProcessors() { + if (loaded) + return; + + // Get the processor service declarations + Collection<ServiceDeclaration> processorDeclarations; + try { + processorDeclarations = + registry.getServiceDiscovery().getServiceDeclarations(StAXAttributeProcessor.class.getName()); + } catch (IOException e) { + IllegalStateException ie = new IllegalStateException(e); + error("IllegalStateException", extensibleStAXAttributeProcessor, ie); + throw ie; + } + + for (ServiceDeclaration processorDeclaration : processorDeclarations) { + Map<String, String> attributes = processorDeclaration.getAttributes(); + + // Load a StAX artifact processor + + // Get the model QName + QName artifactType = ServiceDeclarationParser.getQName(attributes.get("qname")); + + // Get the model class name + String modelTypeName = attributes.get("model"); + + // Get the model factory class name + String factoryName = attributes.get("factory"); + + // Create a processor wrapper and register it + StAXAttributeProcessor<?> processor = + new LazyStAXAttributeProcessor(artifactType, modelTypeName, factoryName, processorDeclaration, + registry, modelFactories, extensibleStAXAttributeProcessor); + addArtifactProcessor(processor); + } + + loaded = true; + } + + /** + * A wrapper around an Artifact processor class allowing lazy loading and + * initialization of artifact processors. + */ + private static class LazyStAXAttributeProcessor implements StAXAttributeProcessor { + + private ExtensionPointRegistry extensionPoints; + private QName artifactType; + private String modelTypeName; + private String factoryName; + private ServiceDeclaration processorDeclaration; + private StAXAttributeProcessor<?> processor; + private Class<?> modelType; + private StAXAttributeProcessor<Object> extensionProcessor; + + LazyStAXAttributeProcessor(QName artifactType, + String modelTypeName, + String factoryName, + ServiceDeclaration processorDeclaration, + ExtensionPointRegistry extensionPoints, + FactoryExtensionPoint modelFactories, + StAXAttributeProcessor<Object> extensionProcessor) { + + this.extensionPoints = extensionPoints; + this.artifactType = artifactType; + this.modelTypeName = modelTypeName; + this.factoryName = factoryName; + this.processorDeclaration = processorDeclaration; + this.extensionProcessor = extensionProcessor; + } + + public QName getArtifactType() { + return artifactType; + } + + @SuppressWarnings("unchecked") + private StAXAttributeProcessor getProcessor() { + if (processor == null) { + FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + + // Load and instantiate the processor class + try { + Class<StAXAttributeProcessor> processorClass = + (Class<StAXAttributeProcessor>)processorDeclaration.loadClass(); + try { + Constructor<StAXAttributeProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class); + processor = constructor.newInstance(modelFactories); + } catch (NoSuchMethodException e) { + try { + Constructor<StAXAttributeProcessor> constructor = + processorClass.getConstructor(ExtensionPointRegistry.class); + processor = constructor.newInstance(extensionPoints); + } catch (NoSuchMethodException e1) { + try { + Constructor<StAXAttributeProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class, + StAXArtifactProcessor.class); + processor = constructor.newInstance(modelFactories, extensionProcessor); + } catch (NoSuchMethodException e2) { + try { + Constructor<StAXAttributeProcessor> constructor = + processorClass.getConstructor(ExtensionPointRegistry.class, + StAXArtifactProcessor.class); + processor = constructor.newInstance(extensionPoints, extensionProcessor); + } catch (NoSuchMethodException e3) { + try { + Constructor<StAXAttributeProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class); + processor = constructor.newInstance(modelFactories); + } catch (NoSuchMethodException e4) { + try { + Constructor<StAXAttributeProcessor> constructor = + processorClass.getConstructor(ExtensionPointRegistry.class); + processor = constructor.newInstance(extensionPoints); + } catch (NoSuchMethodException e4a) { + + Constructor<StAXAttributeProcessor> constructor = + processorClass.getConstructor(); + processor = constructor.newInstance(); + + } + } + } + } + } + } + } catch (Exception e) { + IllegalStateException ie = new IllegalStateException(e); + throw ie; + } + + } + return processor; + } + + public Object read(QName attributeName, XMLStreamReader inputSource, ProcessorContext context) + throws ContributionReadException, XMLStreamException { + return getProcessor().read(attributeName, inputSource, context); + } + + @SuppressWarnings("unchecked") + public void write(Object model, XMLStreamWriter outputSource, ProcessorContext context) + throws ContributionWriteException, XMLStreamException { + getProcessor().write(model, outputSource, context); + } + + public Class<?> getModelType() { + if (modelTypeName != null && modelType == null) { + try { + modelType = processorDeclaration.loadClass(modelTypeName); + } catch (Exception e) { + IllegalStateException ie = new IllegalStateException(e); + throw ie; + } + } + return modelType; + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver, ProcessorContext context) + throws ContributionResolveException { + getProcessor().resolve(model, resolver, context); + } + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..e22d7762fa --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java @@ -0,0 +1,320 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; + +/** + * The default implementation of a URL artifact processor extension point. + * + * @version $Rev$ $Date$ + */ +public class DefaultURLArtifactProcessorExtensionPoint extends + DefaultArtifactProcessorExtensionPoint<URLArtifactProcessor<?>> implements URLArtifactProcessorExtensionPoint { + + private ExtensionPointRegistry registry; + private StAXArtifactProcessor<?> staxProcessor; + private boolean loaded; + + /** + * Constructs a new extension point. + */ + public DefaultURLArtifactProcessorExtensionPoint(ExtensionPointRegistry extensionPoints) { + this.registry = extensionPoints; + FactoryExtensionPoint modelFactories = this.registry.getExtensionPoint(FactoryExtensionPoint.class); + XMLInputFactory inputFactory = modelFactories.getFactory(XMLInputFactory.class); + XMLOutputFactory outputFactory = modelFactories.getFactory(XMLOutputFactory.class); + StAXArtifactProcessorExtensionPoint staxProcessors = + extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, outputFactory); + } + + public void addArtifactProcessor(URLArtifactProcessor<?> artifactProcessor) { + if (artifactProcessor.getArtifactType() != null) { + Pattern pattern = Pattern.compile(wildcard2regex(artifactProcessor.getArtifactType())); + processorsByArtifactType.put(pattern, artifactProcessor); + } + if (artifactProcessor.getModelType() != null) { + processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor); + } + } + + public void removeArtifactProcessor(URLArtifactProcessor<?> artifactProcessor) { + if (artifactProcessor.getArtifactType() != null) { + String regex = wildcard2regex(artifactProcessor.getArtifactType()); + for (Object key : processorsByArtifactType.keySet()) { + if ((key instanceof Pattern) && ((Pattern)key).pattern().equals(regex)) { + processorsByArtifactType.remove(key); + } + } + processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType()); + } + if (artifactProcessor.getModelType() != null) { + processorsByModelType.remove(artifactProcessor.getModelType()); + } + } + + @SuppressWarnings("unchecked") + @Override + public <T> URLArtifactProcessor<T> getProcessor(Class<T> modelType) { + loadProcessors(); + return (URLArtifactProcessor<T>)super.getProcessor(modelType); + } + + public Collection<URLArtifactProcessor<?>> getProcessors(Object artifactType) { + loadProcessors(); + String uri = (String)artifactType; + if (uri.endsWith("/")) { + // Ignore directories + return Collections.emptyList(); + } + if (!uri.startsWith("/")) { + uri = "/" + uri; + } + List<URLArtifactProcessor<?>> processors = new ArrayList<URLArtifactProcessor<?>>(); + for (Map.Entry<Object, URLArtifactProcessor<?>> e : processorsByArtifactType.entrySet()) { + Pattern pattern = (Pattern)e.getKey(); + if (pattern.matcher(uri).matches()) { + processors.add(e.getValue()); + } + } + return processors; + } + + @SuppressWarnings("unchecked") + public URLArtifactProcessor<?> getProcessor(Object artifactType) { + Collection<URLArtifactProcessor<?>> processors = getProcessors(artifactType); + return processors.isEmpty() ? null : processors.iterator().next(); + } + + private static String wildcard2regex(String pattern) { + String wildcard = pattern; + if (wildcard.endsWith("/")) { + // Directory: xyz/ --> xyz/** + wildcard = wildcard + "**"; + } + if (wildcard.startsWith(".")) { + // File extension: .xyz --> **/*.xyz + wildcard = "**/*" + wildcard; + } else if (wildcard.indexOf('/') == -1) { + // File name: abc.txt --> **/abc.txt + wildcard = "**/" + wildcard; + } else if (!(wildcard.startsWith("/") || wildcard.startsWith("**"))) { + wildcard = '/' + wildcard; + } + StringBuffer regex = new StringBuffer(); + char[] chars = wildcard.toCharArray(); + for (int i = 0; i < chars.length; i++) { + switch (chars[i]) { + case '*': + if (i < chars.length - 1 && chars[i + 1] == '*') { + // Next char is '*' + if (i < chars.length - 2) { + if (chars[i + 2] == '/') { + // The wildcard is **/, it matches zero or more directories + regex.append("(.*/)*"); + i += 2; // Skip */ + } else { + // ** can only be followed by / + throw new IllegalArgumentException("** can only be used as the name for a directory"); + } + } else { + regex.append(".*"); + i++; // Skip next * + } + } else { + // Non-directory + regex.append("[^/]*"); + } + break; + case '?': + regex.append("[^/]"); + break; + case '\\': + case '|': + case '(': + case ')': + // case '[': + // case ']': + // case '{': + // case '}': + case '^': + case '$': + case '+': + case '.': + case '<': + case '>': + regex.append("\\").append(chars[i]); + break; + default: + regex.append(chars[i]); + break; + } + } + return regex.toString(); + } + + /** + * Lazily load artifact processors registered in the extension point. + */ + private synchronized void loadProcessors() { + if (loaded) + return; + + // Get the processor service declarations + Collection<ServiceDeclaration> processorDeclarations; + try { + processorDeclarations = + registry.getServiceDiscovery().getServiceDeclarations(URLArtifactProcessor.class.getName()); + } catch (IOException e) { + IllegalStateException ie = new IllegalStateException(e); + throw ie; + } + + for (ServiceDeclaration processorDeclaration : processorDeclarations) { + Map<String, String> attributes = processorDeclaration.getAttributes(); + // Load a URL artifact processor + String artifactType = attributes.get("type"); + String modelTypeName = attributes.get("model"); + + // Create a processor wrapper and register it + URLArtifactProcessor<?> processor = + new LazyURLArtifactProcessor(artifactType, modelTypeName, processorDeclaration, registry, + staxProcessor); + addArtifactProcessor(processor); + } + + loaded = true; + } + + /** + * A wrapper around an Artifact processor class allowing lazy loading and + * initialization of artifact processors. + */ + private static class LazyURLArtifactProcessor implements ExtendedURLArtifactProcessor { + + private ExtensionPointRegistry extensionPoints; + private String artifactType; + private String modelTypeName; + private ServiceDeclaration processorDeclaration; + private URLArtifactProcessor<?> processor; + private Class<?> modelType; + private StAXArtifactProcessor<?> staxProcessor; + + LazyURLArtifactProcessor(String artifactType, + String modelTypeName, + ServiceDeclaration processorDeclaration, + ExtensionPointRegistry extensionPoints, + StAXArtifactProcessor<?> staxProcessor) { + this.artifactType = artifactType; + this.modelTypeName = modelTypeName; + this.processorDeclaration = processorDeclaration; + this.extensionPoints = extensionPoints; + this.staxProcessor = staxProcessor; + } + + public String getArtifactType() { + return artifactType; + } + + @SuppressWarnings("unchecked") + private URLArtifactProcessor getProcessor() { + if (processor == null) { + try { + FactoryExtensionPoint modelFactories = + extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + Class<URLArtifactProcessor> processorClass = + (Class<URLArtifactProcessor>)processorDeclaration.loadClass(); + try { + Constructor<URLArtifactProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class); + processor = constructor.newInstance(modelFactories); + } catch (NoSuchMethodException e) { + try { + Constructor<URLArtifactProcessor> constructor = + processorClass.getConstructor(FactoryExtensionPoint.class, + StAXArtifactProcessor.class); + processor = constructor.newInstance(modelFactories, staxProcessor); + } catch (NoSuchMethodException e2) { + Constructor<URLArtifactProcessor> constructor = + processorClass.getConstructor(ExtensionPointRegistry.class, + StAXArtifactProcessor.class); + processor = constructor.newInstance(extensionPoints, staxProcessor); + } + } + } catch (Throwable e) { + IllegalStateException ie = new IllegalStateException("Exception during getProcessor() for " + + processorDeclaration.getClassName(), e); + throw ie; + } + } + return processor; + } + + public Object read(URL contributionURL, URI artifactURI, URL artifactURL, ProcessorContext context) throws ContributionReadException { + return getProcessor().read(contributionURL, artifactURI, artifactURL, context); + } + + public Class<?> getModelType() { + if (modelTypeName != null && modelType == null) { + try { + modelType = processorDeclaration.loadClass(modelTypeName); + } catch (ClassNotFoundException e) { + IllegalStateException ie = new IllegalStateException(e); + throw ie; + } + } + return modelType; + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + getProcessor().resolve(model, resolver, context); + } // end method resolve + + /** + * Preresolve phase, for ExtendedURLArtifactProcessors only + */ + @SuppressWarnings("unchecked") + public void preResolve( Object model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + URLArtifactProcessor<?> processor = getProcessor(); + if( processor instanceof ExtendedURLArtifactProcessor ) { + ((ExtendedURLArtifactProcessor)processor).preResolve(model, resolver, context); + } // end if + } // end method resolve + + } // end class LazyURLArtifactProcessor +} // end class DefaultURLArtifactProcessorExtensionPoint diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java new file mode 100644 index 0000000000..59fa5990d6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java @@ -0,0 +1,435 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.EventFilter; +import javax.xml.stream.StreamFilter; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.apache.tuscany.sca.assembly.xsd.Constants; +import org.apache.tuscany.sca.common.xml.XMLDocumentHelper; +import org.apache.tuscany.sca.common.xml.stax.StAXHelper; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.extensibility.ClassLoaderContext; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.MonitorFactory; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * Default implementation of an XMLInputFactory that creates validating + * XMLStreamReaders. + * + * @version $Rev$ $Date$ + */ +public class DefaultValidatingXMLInputFactory extends ValidatingXMLInputFactory implements LSResourceResolver { + private ExtensionPointRegistry registry; + private XMLInputFactory inputFactory; + private DocumentBuilderFactory documentBuilderFactory; + private DOMImplementationLS ls; + private ValidationSchemaExtensionPoint schemas; + private MonitorFactory monitorFactory; + private boolean initialized; + private boolean hasSchemas; + private Schema aggregatedSchema; + private StAXHelper helper; + + public DefaultValidatingXMLInputFactory(ExtensionPointRegistry registry) { + this.registry = registry; + FactoryExtensionPoint factoryExtensionPoint = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.inputFactory = factoryExtensionPoint.getFactory(XMLInputFactory.class); + this.documentBuilderFactory = factoryExtensionPoint.getFactory(DocumentBuilderFactory.class); + this.schemas = registry.getExtensionPoint(ValidationSchemaExtensionPoint.class); + this.monitorFactory = + registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(MonitorFactory.class); + this.helper = StAXHelper.getInstance(registry); + } + + /** + * Constructs a new XMLInputFactory. + * + * @param inputFactory + * @param schemas + */ + // FOR Test only + public DefaultValidatingXMLInputFactory(XMLInputFactory inputFactory, ValidationSchemaExtensionPoint schemas) { + this.inputFactory = inputFactory; + this.schemas = schemas; + this.registry = new DefaultExtensionPointRegistry(); + } + + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Throwable ex) { + Monitor.error(monitor, this, "contribution-validation-messages", message, ex); + } + + private void warn(Monitor monitor, String message, Object model, Throwable ex) { + Monitor.warning(monitor, this, "contribution-validation-messages", message, ex); + } + + public static final QName XSD = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "schema"); + + private Collection<? extends Source> aggregate(URL... urls) throws IOException, XMLStreamException { + if (urls.length == 1) { + return Collections.singletonList(new SAXSource(XMLDocumentHelper.getInputSource(urls[0]))); + } + Map<String, Collection<URL>> map = new HashMap<String, Collection<URL>>(); + + for (URL url : urls) { + String tns = helper.readAttribute(url, XSD, "targetNamespace"); + Collection<URL> collection = map.get(tns); + if (collection == null) { + collection = new HashSet<URL>(); + map.put(tns, collection); + } + collection.add(url); + } + List<Source> sources = new ArrayList<Source>(); + for (Map.Entry<String, Collection<URL>> e : map.entrySet()) { + if (e.getValue().size() == 1) { + sources.add(new SAXSource(XMLDocumentHelper.getInputSource(e.getValue().iterator().next()))); + } else { + StringBuffer xsd = new StringBuffer("<schema xmlns=\"http://www.w3.org/2001/XMLSchema\""); + if (e.getKey() != null) { + xsd.append(" targetNamespace=\"").append(e.getKey()).append("\""); + } + xsd.append(">"); + for (URL url : e.getValue()) { + xsd.append("<include schemaLocation=\"").append(url).append("\"/>"); + } + xsd.append("</schema>"); + SAXSource source = new SAXSource(new InputSource(new StringReader(xsd.toString()))); + sources.add(source); + } + } + return sources; + } + + /** + * Initialize the registered schemas and create an aggregated schema for + * validation. + * @param monitor TODO + */ + private synchronized void initializeSchemas(Monitor monitor) { + if (initialized) { + return; + } + initialized = true; + + // Load the XSDs registered in the validation schema extension point + try { + List<String> uris = schemas.getSchemas(); + int n = uris.size(); + if (n ==0) { + return; + } else { + hasSchemas = true; + } + + URL[] urls = new URL[uris.size()]; + for (int i = 0; i < urls.length; i++) { + urls[i] = new URL(uris.get(i)); + } + final Collection<? extends Source> sources = aggregate(urls); + + final SchemaFactory schemaFactory = newSchemaFactory(); + DOMImplementation impl = null; + try { + impl = documentBuilderFactory.newDocumentBuilder().getDOMImplementation(); + } catch (ParserConfigurationException e) { + // Ignore + } + if (impl instanceof DOMImplementationLS) { + ls = (DOMImplementationLS)impl; + schemaFactory.setResourceResolver(this); + } + // Allow privileged access to check files. Requires FilePermission + // in security policy. + try { + aggregatedSchema = AccessController.doPrivileged(new PrivilegedExceptionAction<Schema>() { + public Schema run() throws SAXException { + return schemaFactory.newSchema(sources.toArray(new Source[sources.size()])); + } + }); + } catch (PrivilegedActionException e) { + warn(monitor, "PrivilegedActionException", schemaFactory, (SAXException)e.getException()); + hasSchemas = false; + throw (SAXException)e.getException(); + } + + } catch (SAXException e) { +// IllegalStateException ie = new IllegalStateException(e); +// error("IllegalStateException", schemas, ie); +// throw ie; + } catch (Throwable e) { + //FIXME Log this, some old JDKs don't support XMLSchema validation + warn(monitor, e.getMessage(), schemas, e); + hasSchemas = false; + } + } + + /** + * For OSGi: + * Create a SchemaFactory in the context of service provider classloaders + * @return + */ + private SchemaFactory newSchemaFactory() { + ClassLoader cl = + ClassLoaderContext.setContextClassLoader(getClass().getClassLoader(), + registry.getServiceDiscovery(), + SchemaFactory.class, + TransformerFactory.class, + SAXParserFactory.class, + DocumentBuilderFactory.class + ); + try { + // Create an aggregated validation schemas from all the XSDs + return SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + } finally { + if (cl != null) { + Thread.currentThread().setContextClassLoader(cl); + } + } + } + + @Override + public XMLEventReader createFilteredReader(XMLEventReader arg0, EventFilter arg1) throws XMLStreamException { + return inputFactory.createFilteredReader(arg0, arg1); + } + + @Override + public XMLStreamReader createFilteredReader(XMLStreamReader arg0, StreamFilter arg1) throws XMLStreamException { + return inputFactory.createFilteredReader(arg0, arg1); + } + + @Override + public XMLEventReader createXMLEventReader(InputStream arg0, String arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + @Override + public XMLEventReader createXMLEventReader(InputStream arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + @Override + public XMLEventReader createXMLEventReader(Reader arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + @Override + public XMLEventReader createXMLEventReader(Source arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + @Override + public XMLEventReader createXMLEventReader(String arg0, InputStream arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + @Override + public XMLEventReader createXMLEventReader(String arg0, Reader arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + @Override + public XMLEventReader createXMLEventReader(XMLStreamReader arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream arg0, String arg1) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, monitor); + }else { + return inputFactory.createXMLStreamReader(arg0, arg1); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream arg0) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor); + } else { + return inputFactory.createXMLStreamReader(arg0); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(Reader arg0) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor); + } else { + return inputFactory.createXMLStreamReader(arg0); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(Source arg0) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor); + } else { + return inputFactory.createXMLStreamReader(arg0); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(String arg0, InputStream arg1) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, monitor); + } else { + return inputFactory.createXMLStreamReader(arg0, arg1); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(String arg0, Reader arg1) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, monitor); + } else { + return inputFactory.createXMLStreamReader(arg0, arg1); + } + } + + @Override + public XMLEventAllocator getEventAllocator() { + return inputFactory.getEventAllocator(); + } + + @Override + public Object getProperty(String arg0) throws IllegalArgumentException { + return inputFactory.getProperty(arg0); + } + + @Override + public XMLReporter getXMLReporter() { + return inputFactory.getXMLReporter(); + } + + @Override + public XMLResolver getXMLResolver() { + return inputFactory.getXMLResolver(); + } + + @Override + public boolean isPropertySupported(String arg0) { + return inputFactory.isPropertySupported(arg0); + } + + @Override + public void setEventAllocator(XMLEventAllocator arg0) { + inputFactory.setEventAllocator(arg0); + } + + @Override + public void setProperty(String arg0, Object arg1) throws IllegalArgumentException { + inputFactory.setProperty(arg0, arg1); + } + + @Override + public void setXMLReporter(XMLReporter arg0) { + inputFactory.setXMLReporter(arg0); + } + + @Override + public void setXMLResolver(XMLResolver arg0) { + inputFactory.setXMLResolver(arg0); + } + + public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { + String key = null; + if("http://www.w3.org/2001/XMLSchema".equals(type)) { + key = namespaceURI; + } else if("http://www.w3.org/TR/REC-xml".equals(type)) { + key = publicId; + } + URL url = Constants.CACHED_XSDS.get(key); + if (url != null && !Constants.SCA11_NS.equals(namespaceURI)) { + systemId = url.toString(); + } else if (url != null && systemId == null) { + systemId = url.toString(); + } + + LSInput input = ls.createLSInput(); + input.setBaseURI(baseURI); + input.setPublicId(publicId); + input.setSystemId(systemId); + return input; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java new file mode 100644 index 0000000000..4cb83cd5ef --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java @@ -0,0 +1,123 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; + +/** + * Default implementation of an extension point for XML schemas. + * + * @version $Rev$ $Date$ + */ +public class DefaultValidationSchemaExtensionPoint implements ValidationSchemaExtensionPoint { + private boolean enabled = true; + private List<String> schemas = new ArrayList<String>(); + private boolean loaded; + private ExtensionPointRegistry registry; + + public DefaultValidationSchemaExtensionPoint(ExtensionPointRegistry registry, Map<String, String> attributes) { + super(); + this.registry = registry; + if (attributes != null) { + String attr = attributes.get("enabled"); + if (attr != null) { + enabled = Boolean.parseBoolean(attr); + } + } + } + + public void addSchema(String uri) { + schemas.add(uri); + } + + public void removeSchema(String uri) { + schemas.remove(uri); + } + + /** + * Load schema declarations from META-INF/services/ + * org.apache.tuscany.sca.contribution.processor.ValidationSchema files + */ + private synchronized void loadSchemas() { + if (loaded || (!enabled)) + return; + + // Get the schema declarations + Collection<ServiceDeclaration> schemaDeclarations; + try { + schemaDeclarations = + registry.getServiceDiscovery() + .getServiceDeclarations("org.apache.tuscany.sca.contribution.processor.ValidationSchema"); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + // TODO - temp fix to ensure that the schema tuscany-sca.xsd always comes first + String tuscanyScaXsd = null; + + // Find each schema + for (ServiceDeclaration schemaDeclaration : schemaDeclarations) { + URL url = schemaDeclaration.getResource(schemaDeclaration.getClassName()); + if (url == null) { + throw new IllegalArgumentException(new FileNotFoundException(schemaDeclaration.getClassName())); + } + + if (url.toString().contains("tuscany-sca-1.1.xsd")) { + tuscanyScaXsd = url.toString(); + } else { + schemas.add(url.toString()); + } + } + + if (tuscanyScaXsd != null) { + schemas.add(0, tuscanyScaXsd); + } + + loaded = true; + } + + public List<String> getSchemas() { + if (enabled) { + loadSchemas(); + return schemas; + } else { + return Collections.emptyList(); + } + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedArtifactProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedArtifactProcessor.java new file mode 100644 index 0000000000..ca579110ae --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedArtifactProcessor.java @@ -0,0 +1,41 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * Interface for extended Artifact Processors which require a pre-resolve phase prior to the resolve phase + * + * @version $Rev$ $Date$ + */ +public interface ExtendedArtifactProcessor<M> extends ArtifactProcessor<M> { + + /** + * Pre-resolve references from this model to other models. Used for models where initial setup of + * the resolve phase is required. An example is Contribution models with imports and exports which must + * be set up prior to the main resolve phase + * + * @param model The model to resolve + * @param resolver The resolver to use to resolve referenced models + * @param context The context + */ + void preResolve(M model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException; + +} // end interface diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedURLArtifactProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedURLArtifactProcessor.java new file mode 100644 index 0000000000..2639a21e41 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedURLArtifactProcessor.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + + +/** + * An extended artifact processor that can read models from a URL. + * + * @version $Rev$ $Date$ + */ +public interface ExtendedURLArtifactProcessor<M> extends ExtendedArtifactProcessor<M>, URLArtifactProcessor<M> { + +} // end interface diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java new file mode 100644 index 0000000000..132b7a8858 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java @@ -0,0 +1,283 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.Extension; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Implementation of an extensible StAX artifact processor. + * + * Takes a StAXArtifactProcessorExtensionPoint and delegates to the proper + * StAXArtifactProcessor by element QName + * + * @version $Rev$ $Date$ + */ +public class ExtensibleStAXArtifactProcessor implements StAXArtifactProcessor<Object> { + private static final Logger logger = Logger.getLogger(ExtensibleStAXArtifactProcessor.class.getName()); + private static final String XMLSCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; + public static final QName ANY_ELEMENT = new QName(XMLSCHEMA_NS, "any"); + + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXArtifactProcessorExtensionPoint processors; + + /** + * Constructs a new ExtensibleStAXArtifactProcessor. + * @param processors + * @param inputFactory + * @param outputFactory + */ + public ExtensibleStAXArtifactProcessor(StAXArtifactProcessorExtensionPoint processors, + XMLInputFactory inputFactory, + XMLOutputFactory outputFactory) { + super(); + this.processors = processors; + this.inputFactory = inputFactory; + this.outputFactory = outputFactory; + if (this.outputFactory != null) { + this.outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); + } + } + + public ExtensibleStAXArtifactProcessor(ExtensionPointRegistry registry) { + super(); + this.processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.inputFactory = factories.getFactory(XMLInputFactory.class); + this.outputFactory = factories.getFactory(XMLOutputFactory.class); + if (this.outputFactory != null) { + this.outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); + } + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void warning(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.WARNING, + model, + message, + (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.ERROR, + model, + message, + (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.ERROR, + model, + message, + ex); + monitor.problem(problem); + } + } + + public Object read(XMLStreamReader source, ProcessorContext context) throws ContributionReadException, XMLStreamException { + Monitor monitor = context.getMonitor(); + // Delegate to the processor associated with the element QName + int event = source.getEventType(); + if (event == XMLStreamConstants.START_DOCUMENT) { + source.nextTag(); + } + QName name = source.getName(); + StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(name); + if (processor == null) { + Location location = source.getLocation(); + error(monitor, "ElementCannotBeProcessed", processors, name, location); + + StAXArtifactProcessor anyElementProcessor = processors.getProcessor(ANY_ELEMENT); + if (anyElementProcessor != null) { + return anyElementProcessor.read(source, context); + } else { + return null; + } + } + return processor.read(source, context); + } + + @SuppressWarnings("unchecked") + public void write(Object model, XMLStreamWriter outputSource, ProcessorContext context) throws ContributionWriteException, XMLStreamException { + // Delegate to the processor associated with the model type + if (model != null) { + StAXArtifactProcessor processor = processors.getProcessor(model.getClass()); + if (processor != null) { + processor.write(model, outputSource, context); + } else { + if (logger.isLoggable(Level.WARNING)) { + logger.warning("No StAX processor is configured to handle " + model.getClass()); + } + StAXArtifactProcessor anyElementProcessor = processors.getProcessor(ANY_ELEMENT); + if ((model instanceof Extension) && anyElementProcessor != null) { + anyElementProcessor.write(model, outputSource, context); + } + } + } + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + + // Delegate to the processor associated with the model type + if (model != null) { + StAXArtifactProcessor processor = processors.getProcessor(model.getClass()); + if (processor != null) { + processor.resolve(model, resolver, context); + } + } + } + + /** + * Read a model from an InputStream. + * @param is The artifact InputStream + * @param type Model type + * @param context TODO + * @return The model + * @throws ContributionReadException + */ + public <M> M read(InputStream is, Class<M> type, ProcessorContext context) throws ContributionReadException { + Monitor monitor = context.getMonitor(); + try { + XMLStreamReader reader; + try { + reader = inputFactory.createXMLStreamReader(is); + try { + reader.nextTag(); + QName name = reader.getName(); + Object mo = read(reader, context); + if (type.isInstance(mo)) { + return type.cast(mo); + } else { + error(monitor, "UnrecognizedElementException", reader, name); + UnrecognizedElementException e = new UnrecognizedElementException(name); + throw e; + } + } catch (ContributionReadException e) { + Location location = reader.getLocation(); + e.setLine(location.getLineNumber()); + e.setColumn(location.getColumnNumber()); + error(monitor, "ContributionReadException", reader, e); + throw e; + } finally { + try { + reader.close(); + } catch (XMLStreamException e) { + // ignore + } + } + } finally { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } catch (XMLStreamException e) { + ContributionReadException ce = new ContributionReadException(e); + error(monitor, "ContributionReadException", inputFactory, ce); + throw ce; + } + } + + /** + * Write a model to an OutputStream. + * @param model + * @param os + * @param context + * @throws ContributionWriteException + */ + public void write(Object model, OutputStream os, ProcessorContext context) throws ContributionWriteException { + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(os); + write(model, writer, context); + writer.flush(); + writer.close(); + } catch (XMLStreamException e) { + ContributionWriteException cw = new ContributionWriteException(e); + error(context.getMonitor(), "ContributionWriteException", outputFactory, cw); + throw cw; + } + } + + public QName getArtifactType() { + return null; + } + + public Class<Object> getModelType() { + return null; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java new file mode 100644 index 0000000000..5bf7e88779 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java @@ -0,0 +1,259 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.Extension; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Implementation of an extensible StAX attribute processor. + * + * Takes a StAXAttributeProcessorExtensionPoint and delegates to the proper + * StAXAttributeProcessor by attribute QName + * + * @version $Rev$ $Date$ + */ +public class ExtensibleStAXAttributeProcessor implements StAXAttributeProcessor<Object> { + + private static final Logger logger = Logger.getLogger(ExtensibleStAXAttributeProcessor.class.getName()); + private static final String XMLSCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; + public static final QName ANY_ATTRIBUTE = new QName(XMLSCHEMA_NS, "anyAttribute"); + + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXAttributeProcessorExtensionPoint processors; + /** + * Constructs a new ExtensibleStAXArtifactProcessor. + * @param processors + * @param inputFactory + * @param outputFactory + */ + public ExtensibleStAXAttributeProcessor(StAXAttributeProcessorExtensionPoint processors, + XMLInputFactory inputFactory, + XMLOutputFactory outputFactory) { + super(); + this.processors = processors; + this.inputFactory = inputFactory; + this.outputFactory = outputFactory; + if (this.outputFactory != null) { + this.outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); + } + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void warning(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.WARNING, + model, + message, + (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.ERROR, + model, + message, + (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.ERROR, + model, + message, + ex); + monitor.problem(problem); + } + } + + public Object read(QName attributeName, XMLStreamReader source, ProcessorContext context) throws ContributionReadException, + XMLStreamException { + // Delegate to the processor associated with the attribute QName + int event = source.getEventType(); + if (event == XMLStreamConstants.START_DOCUMENT) { + while (source.next() != XMLStreamReader.START_ELEMENT); + } + + StAXAttributeProcessor<?> processor = null; + + //lookup for registered attribute processors + processor = (StAXAttributeProcessor<?>)processors.getProcessor(attributeName); + if (processor == null) { + Location location = source.getLocation(); + // Skip xsi:type, xsi:nil and xsi:schemaLocation etc + if (!W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(attributeName.getNamespaceURI())) { + if (logger.isLoggable(Level.WARNING)) { + logger.warning("Attribute " + attributeName + " cannot be processed. (" + location + ")"); + } + warning(context.getMonitor(), "AttributeCannotBeProcessed", processors, attributeName, location); + } + } else { + return processor.read(attributeName, source, context); + } + + //handle extension attributes without processors + processor = (StAXAttributeProcessor<?>)processors.getProcessor(ANY_ATTRIBUTE); + if (processor == null) { + Location location = source.getLocation(); + if (logger.isLoggable(Level.WARNING)) { + logger.warning("Could not find Default Attribute processor !"); + } + warning(context.getMonitor(), "DefaultAttributeProcessorNotAvailable", processors, ANY_ATTRIBUTE, location); + } + + return processor == null ? null : processor.read(attributeName, source, context); + } + + @SuppressWarnings("unchecked") + public void write(Object model, XMLStreamWriter outputSource, ProcessorContext context) throws ContributionWriteException, XMLStreamException { + + if (model == null) { + return; + } + + // Delegate to the processor associated with the model type + StAXAttributeProcessor processor = processors.getProcessor(model.getClass()); + if (processor == null) { + if (!Extension.class.isInstance(model)) { + if (logger.isLoggable(Level.WARNING)) { + logger.warning("No StAX processor is configured to handle " + model.getClass()); + } + warning(context.getMonitor(), "NoStaxProcessor", processors, model.getClass()); + } + } else { + processor.write(model, outputSource, context); + return; + } + + //handle extension attributes without processors + processor = (StAXAttributeProcessor<?>)processors.getProcessor(ANY_ATTRIBUTE); + if (processor == null) { + if (logger.isLoggable(Level.WARNING)) { + logger.warning("No Default StAX processor is configured to handle " + model.getClass()); + } + warning(context.getMonitor(), "NoDefaultStaxProcessor", processors, model.getClass()); + } else { + processor.write(model, outputSource, context); + return; + } + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + + // Delegate to the processor associated with the model type + if (model != null) { + StAXAttributeProcessor processor = processors.getProcessor(model.getClass()); + if (processor != null) { + processor.resolve(model, resolver, context); + } + } + } + + /** + * Read a model from an InputStream. + * @param is The artifact InputStream + * @param type Model type + * @return The model + * @throws ContributionReadException + */ + public <M> M read(InputStream is, Class<M> type) throws ContributionReadException { + return null; + } + + /** + * Write a model to an OutputStream. + * @param model + * @param os + * @throws ContributionWriteException + */ + public void write(Object model, OutputStream os, ProcessorContext context) throws ContributionWriteException { + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(os); + write(model, writer, context); + writer.flush(); + writer.close(); + } catch (XMLStreamException e) { + ContributionWriteException cw = new ContributionWriteException(e); + error(context.getMonitor(), "ContributionWriteException", outputFactory, cw); + throw cw; + } + } + + public QName getArtifactType() { + return null; + } + + public Class<Object> getModelType() { + return Object.class; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java new file mode 100644 index 0000000000..2491e22a29 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java @@ -0,0 +1,148 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.net.URI; +import java.net.URL; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Implementation of an extensible URL artifact processor. + * + * Takes a URLArtifactProcessorExtensionPoint and delegates to the proper URLArtifactProcessor + * by either fileName or fileExtention + * + * @version $Rev$ $Date$ + */ +public class ExtensibleURLArtifactProcessor implements URLArtifactProcessor<Object> { + + private URLArtifactProcessorExtensionPoint processors; + + /** + * Constructs a new ExtensibleURLArtifactProcessor. + * + * @param processors + */ + public ExtensibleURLArtifactProcessor(URLArtifactProcessorExtensionPoint processors) { + this.processors = processors; + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-validation-messages", + Severity.ERROR, + model, + message, + (Object[])messageParameters); + monitor.problem(problem); + } + } + + @SuppressWarnings("unchecked") + public Object read(URL contributionURL, URI sourceURI, URL sourceURL, ProcessorContext context) throws ContributionReadException { + URLArtifactProcessor<Object> processor = null; + if (sourceURI != null) { + //try to retrieve a processor for the specific URI + String uri = sourceURI.toString(); + if (!uri.startsWith("/")) { + uri = "/" + uri; + } + // Register the URI as the artifact type starts with / + processor = (URLArtifactProcessor<Object>)processors.getProcessor(uri); + } + + /* + if (processor == null) { + // Delegate to the processor associated with file extension + String fileName = getFileName(sourceURL); + + //try to retrieve a processor for the specific filename + processor = (URLArtifactProcessor<Object>)processors.getProcessor(fileName); + } + + if (processor == null) { + //try to find my file type (extension) + String extension = sourceURL.getPath(); + + int extensionStart = extension.lastIndexOf('.'); + //handle files without extension (e.g NOTICE) + if (extensionStart > 0) { + // File extensions are registered as .<extension> + extension = extension.substring(extensionStart); + processor = (URLArtifactProcessor<Object>)processors.getProcessor(extension); + } + } + */ + + if (processor == null) { + return null; + } + if (context != null && context.getMonitor() != null){ + context.getMonitor().setArtifactName(null); //Reset Artifact Name in Monitor + } + return processor.read(contributionURL, sourceURI, sourceURL, context); + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + + // Delegate to the processor associated with the model type + if (model != null) { + URLArtifactProcessor processor = processors.getProcessor(model.getClass()); + if (processor != null) { + processor.resolve(model, resolver, context); + } + } + } + + public <M> M read(URL contributionURL, URI artifactURI, URL artifactUrl, ProcessorContext context, Class<M> type) + throws ContributionReadException { + Object mo = read(contributionURL, artifactURI, artifactUrl, context); + if (type.isInstance(mo)) { + return type.cast(mo); + } else { + UnrecognizedElementException e = new UnrecognizedElementException(null); + e.setResourceURI(artifactURI.toString()); + error(context.getMonitor(), "UnrecognizedElementException", processors, artifactURI.toString()); + throw e; + } + } + + public String getArtifactType() { + return ""; + } + + public Class<Object> getModelType() { + return Object.class; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ProcessorContext.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ProcessorContext.java new file mode 100644 index 0000000000..d464af40f2 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ProcessorContext.java @@ -0,0 +1,127 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.monitor.DefaultMonitorFactory; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.MonitorFactory; + +/** + * Context for contribution processors + * @tuscany.spi.extension.asclient + */ +public class ProcessorContext { + protected Contribution contribution; + protected Artifact artifact; + protected Monitor monitor; + protected Object parentModel; + + /** + * @param contribution + * @param monitor + */ + public ProcessorContext(Contribution contribution, Monitor monitor) { + super(); + this.contribution = contribution; + this.monitor = monitor; + } + + public ProcessorContext(Monitor monitor) { + super(); + this.monitor = monitor; + } + + public ProcessorContext(ExtensionPointRegistry registry) { + super(); + MonitorFactory monitorFactory = + registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(MonitorFactory.class); + this.monitor = monitorFactory.createMonitor(); + } + + public ProcessorContext() { + super(); + this.monitor = new DefaultMonitorFactory().createMonitor(); + } + + /** + * Get the current contribution + * @return The current contribution + */ + public Contribution getContribution() { + return contribution; + } + + /** + * Set the current contribution + * @param contribution + * @return + */ + public Contribution setContribution(Contribution contribution) { + Contribution old = this.contribution; + this.contribution = contribution; + return old; + } + + public Monitor getMonitor() { + return monitor; + } + + public Monitor setMonitor(Monitor monitor) { + Monitor old = this.monitor; + this.monitor = monitor; + return old; + } + + public Object getParentModel() { + return parentModel; + } + + public Object setParentModel(Object parentMObject) { + Object old = this.parentModel; + this.parentModel = parentMObject; + return old; + } + + /** + * Get the current artifact + * @return The current artifact + */ + public Artifact getArtifact() { + return artifact; + } + + /** + * Set the current artifact. This should be called by URLArtifactProcessor to set the document + * context (such as the URI of the composite file). + * + * @param artifact The new artifact + * @return The old artifact + */ + public Artifact setArtifact(Artifact artifact) { + Artifact old = this.artifact; + this.artifact = artifact; + return old; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java new file mode 100644 index 0000000000..cbdb5c38a0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + + +/** + * An artifact processor that can read models from a StAX XMLStreamReader. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface StAXArtifactProcessor<M> extends ArtifactProcessor<M> { + + /** + * Reads a model from an XMLStreamReader. + * + * @param reader The XMLStreamReader + * @param context The context + * @return A model representation of the input. + */ + M read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException; + + /** + * Writes a model to an XMLStreamWriter. + * + * @param model A model representing the source + * @param writer The XML stream writer + * @param context TODO + * @throws ContributionWriteException + * @throws XMLStreamException + */ + void write(M model, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException; + + /** + * Returns the type of artifact handled by this artifact processor. + * + * @return The type of artifact handled by this artifact processor + */ + QName getArtifactType(); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..a5c66bc1ee --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java @@ -0,0 +1,57 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +/** + * An extension point for StAX artifact processors. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface StAXArtifactProcessorExtensionPoint { + /** + * Add an artifact processor. + * + * @param artifactProcessor The artifact processor to add + */ + void addArtifactProcessor(StAXArtifactProcessor<?> artifactProcessor); + + /** + * Remove an artifact processor. + * + * @param artifactProcessor The artifact processor to remove + */ + void removeArtifactProcessor(StAXArtifactProcessor<?> artifactProcessor); + + /** + * Returns the processor associated with the given artifact type. + * + * @param artifactType An artifact type + * @return The processor associated with the given artifact type + */ + <T> StAXArtifactProcessor<T> getProcessor(Object artifactType); + + /** + * Returns the processor associated with the given model type. + * + * @param modelType A model type + * @return The processor associated with the given model type + */ + <T> StAXArtifactProcessor<T> getProcessor(Class<T> modelType); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java new file mode 100644 index 0000000000..e9fca5fc4c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + + + +/** + * An artifact processor that can read attributes from a StAX XMLStreamReader. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface StAXAttributeProcessor<M> extends ArtifactProcessor<M>{ + + /** + * Reads a model from an XMLStreamReader. + * @param reader The XMLStreamReader + * @param context The context + * + * @return A model representation of the input. + */ + M read(QName attributeName, XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException; + + /** + * Writes a model to an XMLStreamWriter. + * + * @param model A model representing the source + * @param writer The XML stream writer + * @param context The context + * @throws ContributionWriteException + * @throws XMLStreamException + */ + void write(M model, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException; + + /** + * Returns the type of artifact handled by this artifact processor. + * + * @return The type of artifact handled by this artifact processor + */ + QName getArtifactType(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java new file mode 100644 index 0000000000..dbc0a2c7bc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java @@ -0,0 +1,56 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +/** + * An extension point for StAX artifact processors. + * + * @version $Rev$ $Date$ + */ +public interface StAXAttributeProcessorExtensionPoint { + /** + * Add an artifact processor. + * + * @param artifactProcessor The artifact processor to add + */ + void addArtifactProcessor(StAXAttributeProcessor<?> artifactProcessor); + + /** + * Remove an artifact processor. + * + * @param artifactProcessor The artifact processor to remove + */ + void removeArtifactProcessor(StAXAttributeProcessor<?> artifactProcessor); + + /** + * Returns the processor associated with the given artifact type. + * + * @param artifactType An artifact type + * @return The processor associated with the given artifact type + */ + <T> StAXAttributeProcessor<T> getProcessor(Object artifactType); + + /** + * Returns the processor associated with the given model type. + * + * @param modelType A model type + * @return The processor associated with the given model type + */ + <T> StAXAttributeProcessor<T> getProcessor(Class<T> modelType); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java new file mode 100644 index 0000000000..035a753649 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.net.URI; +import java.net.URL; + + +/** + * An artifact processor that can read models from a URL. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface URLArtifactProcessor<M> extends ArtifactProcessor<M> { + + /** + * Reads a model from a URL. + * + * @param contributionURL Contribution location URL + * @param artifactURI Artifact URI + * @param artifactURL Artifact location URL + * @param context The context + * @return A model representation of the input. + */ + M read(URL contributionURL, URI artifactURI, URL artifactURL, ProcessorContext context) throws ContributionReadException; + + /** + * Returns the type of artifact handled by this artifact processor. + * + * @return The type of artifact handled by this artifact processor + */ + String getArtifactType(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..e5b3492767 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java @@ -0,0 +1,66 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.util.Collection; + +/** + * An extension point for URL artifact processors. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface URLArtifactProcessorExtensionPoint { + /** + * Add an artifact processor. + * + * @param artifactProcessor The artifact processor to add + */ + void addArtifactProcessor(URLArtifactProcessor<?> artifactProcessor); + + /** + * Remove an artifact processor. + * + * @param artifactProcessor The artifact processor to remove + */ + void removeArtifactProcessor(URLArtifactProcessor<?> artifactProcessor); + + /** + * Returns the processor associated with the given artifact type. + * + * @param artifactType An artifact type + * @return The processor associated with the given artifact type + */ + <T> URLArtifactProcessor<T> getProcessor(Object artifactType); + + /** + * Returns the processor associated with the given model type. + * + * @param modelType A model type + * @return The processor associated with the given model type + */ + <T> URLArtifactProcessor<T> getProcessor(Class<T> modelType); + + /** + * Return a collection of artifact processors that match the artifactType + * @param artifactType + * @return A collection of processors + */ + Collection<URLArtifactProcessor<?>> getProcessors(Object artifactType); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java new file mode 100644 index 0000000000..4c6f0b7282 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java @@ -0,0 +1,48 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + +import javax.xml.namespace.QName; + +/** + * Exception that indicates an element was encountered that could not be handled. + * + * @version $Rev$ $Date$ + */ +public class UnrecognizedElementException extends ContributionReadException { + private static final long serialVersionUID = 2549543622209829032L; + private final QName element; + + /** + * Constructor that indicates which element could not be handled. + * @param element the element that could not be handled + */ + public UnrecognizedElementException(QName element) { + super("Unrecognized element: " + element); + this.element = element; + } + + /** + * Returns the element that could not be handled. + * @return the element that could not be handled. + */ + public QName getElement() { + return element; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java new file mode 100644 index 0000000000..8a166e42f0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java @@ -0,0 +1,43 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + + +/** + * Exception thrown to indicate that a Content-Type is not supported by this SCA Domain. + * The Content-Type value supplied will be returned as the message text for this exception. + * + * FIXME Don't use as it's deprecated and replaced by UnsupportedPackageTypeException. + * + * @version $Rev$ $Date$ + */ +@Deprecated +public class UnsupportedContentTypeException extends ContributionException { + private static final long serialVersionUID = -1831797280021355672L; + + /** + * Constructs a new UnsupportedContentTypeException. + * + * @param message + */ + public UnsupportedContentTypeException(String message) { + super(message); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java new file mode 100644 index 0000000000..ce94cef6a0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java @@ -0,0 +1,40 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor; + + +/** + * Exception thrown to indicate that a Content-Type is not supported by this SCA Domain. + * The Content-Type value supplied will be returned as the message text for this exception. + * + * @version $Rev$ $Date$ + */ +public class UnsupportedPackageTypeException extends ContributionException { + private static final long serialVersionUID = -1831797280021355672L; + + /** + * Constructs a new UnsupportedPackageTypeException. + * + * @param message + */ + public UnsupportedPackageTypeException(String message) { + super(message); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java new file mode 100644 index 0000000000..0ad8259287 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java @@ -0,0 +1,49 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * Base marker class for validating XML input factories. + * + * @version $Rev$ $Date$ + */ +public abstract class ValidatingXMLInputFactory extends XMLInputFactory { + + /** + * Allows the monitor to be set in lieu of the context being passed + * into the create methods. The base definitions of the create methods + * don't allow for this. + * + * @param reader the XMLStreamReader instance + * @param monitor the current monitor object + * + * @tuscany.spi.extension.asclient + */ + public static void setMonitor(XMLStreamReader reader, Monitor monitor) { + if (reader instanceof ValidatingXMLStreamReader) { + ((ValidatingXMLStreamReader)reader).setMonitor(monitor); + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java new file mode 100644 index 0000000000..6de25d4eeb --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java @@ -0,0 +1,409 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.util.logging.Logger; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.StreamReaderDelegate; +import javax.xml.validation.Schema; +import javax.xml.validation.ValidatorHandler; + +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; +import org.xml.sax.Attributes; +import org.xml.sax.ErrorHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * + * A validating XMLStreamReader that reports XMLSchema validation errors. + * + * @version $Rev$ $Date$ + */ +class ValidatingXMLStreamReader extends StreamReaderDelegate implements XMLStreamReader { + + private static final Logger logger = Logger.getLogger(ValidatingXMLStreamReader.class.getName()); + + private ValidatorHandler handler; + private Schema schema; + private Monitor monitor; + + /** + * Constructs a new ValidatingXMLStreamReader. + * + * @param reader + * @param schema + * @throws XMLStreamException + */ + ValidatingXMLStreamReader(XMLStreamReader reader, Schema schema, Monitor monitor) throws XMLStreamException { + super(reader); + this.monitor = monitor; + this.schema = schema; + } + + void setMonitor(Monitor monitor) { + this.monitor = monitor; + } + + private synchronized ValidatorHandler getHandler() throws XMLStreamException { + if (schema == null || handler!=null) { + return handler; + } + handler = schema.newValidatorHandler(); + handler.setDocumentLocator(new LocatorAdapter()); + try { + handler.setFeature("http://xml.org/sax/features/namespace-prefixes", true); + } catch (SAXException e) { + XMLStreamException xse = new XMLStreamException(e); + error("XMLStreamException", handler, xse); + throw xse; + } + + // These validation errors are just warnings for us as we want to support + // running from an XML document with XSD validation errors, as long as we can + // get the metadata we need from the document + handler.setErrorHandler(new ErrorHandler() { + private String getMessage(SAXParseException e) { + return "XMLSchema validation problem in: " + getArtifactName( e.getSystemId() ) + ", line: " + e.getLineNumber() + ", column: " + e.getColumnNumber() + "\n" + e.getMessage(); + } + + public void error(SAXParseException exception) throws SAXException { + if (ValidatingXMLStreamReader.this.monitor == null) + logger.warning(getMessage(exception)); + else + ValidatingXMLStreamReader.this.error("SchemaError", ValidatingXMLStreamReader.this.getClass(), getArtifactName( exception.getSystemId() ), + exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage()); + } + + public void fatalError(SAXParseException exception) throws SAXException { + if (ValidatingXMLStreamReader.this.monitor == null) + logger.warning(getMessage(exception)); + else + ValidatingXMLStreamReader.this.error("SchemaFatalError", ValidatingXMLStreamReader.this.getClass(), getArtifactName( exception.getSystemId() ), + exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage()); + } + + public void warning(SAXParseException exception) throws SAXException { + if (ValidatingXMLStreamReader.this.monitor == null) + logger.warning(getMessage(exception)); + else + ValidatingXMLStreamReader.this.warning("SchemaWarning", ValidatingXMLStreamReader.this.getClass(), getArtifactName( exception.getSystemId() ), + exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage()); + } + + private String getArtifactName( String input ) { + String artifactName = null; + if( ValidatingXMLStreamReader.this.monitor != null ) { + artifactName = ValidatingXMLStreamReader.this.monitor.getArtifactName(); + } + if (artifactName == null){ + artifactName = input; + } + return artifactName; + } + }); + return handler; + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void warning(String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + @Override + public int next() throws XMLStreamException { + if (getHandler() == null) { + return super.next(); + } + + int event = super.getEventType(); + try { + if (event == START_DOCUMENT) { + // We need to trigger the startDocument() + handler.startDocument(); + } + event = super.next(); + validate(event); + } catch (SAXException e) { + XMLStreamException xse = new XMLStreamException(e.getMessage(), e); + error("XMLStreamException", handler, xse); + throw xse; + } + return event; + } + + private void validate(int event) throws SAXException { + switch (event) { + case START_DOCUMENT: + handler.startDocument(); + break; + case START_ELEMENT: + handleStartElement(); + break; + case PROCESSING_INSTRUCTION: + handler.processingInstruction(super.getPITarget(), super.getPIData()); + break; + case CHARACTERS: + case CDATA: + case SPACE: + case ENTITY_REFERENCE: + handler.characters(super.getTextCharacters(), super.getTextStart(), super.getTextLength()); + break; + case END_ELEMENT: + handleEndElement(); + break; + case END_DOCUMENT: + handler.endDocument(); + break; + } + } + + @Override + public int nextTag() throws XMLStreamException { + if (getHandler() == null) { + return super.nextTag(); + } + while (true) { + int event = super.getEventType(); + try { + if (event == START_DOCUMENT) { + // We need to trigger the startDocument() + handler.startDocument(); + } + event = super.next(); + validate(event); + } catch (SAXException e) { + XMLStreamException xse = new XMLStreamException(e); + error("XMLStreamException", handler, xse); + throw xse; + } + + if ((event == CHARACTERS && isWhiteSpace()) // skip whitespace + || (event == CDATA && isWhiteSpace()) + // skip whitespace + || event == SPACE + || event == PROCESSING_INSTRUCTION + || event == COMMENT) { + continue; + } + if (event != START_ELEMENT && event != END_ELEMENT) { + throw new XMLStreamException("expected start or end tag", getLocation()); + } + return event; + } + } + + @Override + public String getElementText() throws XMLStreamException { + if (getHandler() == null) { + return super.getElementText(); + } + + if (getEventType() != START_ELEMENT) { + return super.getElementText(); + } + StringBuffer text = new StringBuffer(); + + for (;;) { + int event = next(); + switch (event) { + case END_ELEMENT: + return text.toString(); + + case COMMENT: + case PROCESSING_INSTRUCTION: + continue; + + case CHARACTERS: + case CDATA: + case SPACE: + case ENTITY_REFERENCE: + text.append(getText()); + break; + + default: + break; + } + } + } + + @Override + public NamespaceContext getNamespaceContext(){ + return super.getNamespaceContext(); + } + + /** + * Handle a start element event. + * + * @throws SAXException + */ + private void handleStartElement() throws SAXException { + + // send startPrefixMapping events immediately before startElement event + int nsCount = super.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + String prefix = super.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.startPrefixMapping(prefix, super.getNamespaceURI(i)); + } + + // fire startElement + QName qname = super.getName(); + String prefix = qname.getPrefix(); + String rawname; + if (prefix == null || prefix.length() == 0) { + rawname = qname.getLocalPart(); + } else { + rawname = prefix + ':' + qname.getLocalPart(); + } + Attributes attrs = getAttributes(); + handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs); + } + + /** + * Handle an endElement event. + * + * @throws SAXException + */ + private void handleEndElement() throws SAXException { + + // fire endElement + QName qname = super.getName(); + handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), qname.toString()); + + // send endPrefixMapping events immediately after endElement event + // we send them in the opposite order to that returned but this is not + // actually required by SAX + int nsCount = super.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = super.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.endPrefixMapping(prefix); + } + } + + /** + * Get the attributes associated with the current START_ELEMENT event. + * + * @return the StAX attributes converted to org.xml.sax.Attributes + */ + private Attributes getAttributes() { + AttributesImpl attrs = new AttributesImpl(); + + // add namespace declarations + for (int i = 0; i < super.getNamespaceCount(); i++) { + String prefix = super.getNamespacePrefix(i); + String uri = super.getNamespaceURI(i); + if (prefix == null) { + attrs.addAttribute("", "", "xmlns", "CDATA", uri); + } else { + attrs.addAttribute("", "", "xmlns:" + prefix, "CDATA", uri); + } + } + + // Regular attributes + for (int i = 0; i < super.getAttributeCount(); i++) { + String uri = super.getAttributeNamespace(i); + if (uri == null) { + uri = ""; + } + String localName = super.getAttributeLocalName(i); + String prefix = super.getAttributePrefix(i); + String qname; + if (prefix == null || prefix.length() == 0) { + qname = localName; + } else { + qname = prefix + ':' + localName; + } + String type = super.getAttributeType(i); + String value = super.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qname, type, value); + } + + return attrs; + } + + /** + * Adapter for mapping Locator information. + */ + private final class LocatorAdapter implements Locator { + + private LocatorAdapter() { + } + + public int getColumnNumber() { + Location location = getLocation(); + return location == null ? 0 : location.getColumnNumber(); + } + + public int getLineNumber() { + Location location = getLocation(); + return location == null ? 0 : location.getLineNumber(); + } + + public String getPublicId() { + Location location = getLocation(); + return location == null ? "" : location.getPublicId(); + } + + public String getSystemId() { + Location location = getLocation(); + return location == null ? "" : location.getSystemId(); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java new file mode 100644 index 0000000000..67ec55b72e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.util.List; + + +/** + * An extension point for XML schemas used for validation. + * + * @version $Rev$ $Date$ + */ +public interface ValidationSchemaExtensionPoint { + /** + * Set the flag to control if schema validation should be enabled + * @param enabled + */ + void setEnabled(boolean enabled); + + /** + * Test the schema validation is enabled + * @return + */ + boolean isEnabled(); + + /** + * Add a schema. + * + * @param uri the URI of the schema + */ + void addSchema(String uri); + + /** + * Remove a schema. + * + * @param uri the URI of the schema + */ + void removeSchema(String uri); + + /** + * Returns the list of schemas registered in the extension point. + * @return the list of schemas + */ + List<String> getSchemas(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java new file mode 100644 index 0000000000..6e6346fe47 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java @@ -0,0 +1,329 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor.impl; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.List; +import java.util.ListIterator; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ContributionMetadata; +import org.apache.tuscany.sca.contribution.DefaultExport; +import org.apache.tuscany.sca.contribution.DefaultImport; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.java.JavaExport; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ExtendedURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.DefaultModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint; +import org.apache.tuscany.sca.contribution.scanner.ContributionScanner; +import org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint; +import org.apache.tuscany.sca.contribution.scanner.impl.DirectoryContributionScanner; +import org.apache.tuscany.sca.contribution.scanner.impl.JarContributionScanner; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * URLArtifactProcessor that handles contribution files and the artifacts they contain + * and returns a contribution model. + * + * @version $Rev$ $Date$ + */ +public class ContributionContentProcessor implements ExtendedURLArtifactProcessor<Contribution>{ + private ContributionFactory contributionFactory; + private ModelResolverExtensionPoint modelResolvers; + private FactoryExtensionPoint modelFactories; + private URLArtifactProcessor<Object> artifactProcessor; + private StAXArtifactProcessor<Object> extensionProcessor; + private ContributionScannerExtensionPoint scanners; + // Marks pre-resolve phase completed + private boolean preResolved = false; + + public ContributionContentProcessor(ExtensionPointRegistry extensionPoints, StAXArtifactProcessor<Object> extensionProcessor) { + this.modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + this.modelResolvers = extensionPoints.getExtensionPoint(ModelResolverExtensionPoint.class); + URLArtifactProcessorExtensionPoint artifactProcessors = extensionPoints.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + this.artifactProcessor = new ExtensibleURLArtifactProcessor(artifactProcessors); + this.extensionProcessor = extensionProcessor; + this.contributionFactory = modelFactories.getFactory(ContributionFactory.class); + this.scanners = extensionPoints.getExtensionPoint(ContributionScannerExtensionPoint.class); + } + + public String getArtifactType() { + return ".contribution/content"; + } + + public Class<Contribution> getModelType() { + return Contribution.class; + } + + private File toFile(URL url) { + if("file".equalsIgnoreCase(url.getProtocol())) { + try { + return new File(url.toURI()); + } catch(URISyntaxException e) { + return new File(url.getPath()); + } catch(IllegalArgumentException e) { + // Hack for file:./a.txt or file:../a/c.wsdl + return new File(url.getPath()); + } + } + return null; + } + + public Contribution read(URL parentURL, URI contributionURI, URL contributionURL, ProcessorContext context) throws ContributionReadException { + + + // Create contribution model + Contribution contribution = contributionFactory.createContribution(); + contribution.setURI(contributionURI.toString()); + contribution.setLocation(contributionURL.toString()); + ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, modelFactories); + contribution.setModelResolver(modelResolver); + contribution.setUnresolved(true); + + Monitor monitor = context.getMonitor(); + monitor.pushContext("Contribution: " + contribution.getURI()); + + Contribution old = context.setContribution(contribution); + try { + // Create a contribution scanner + ContributionScanner scanner = scanners.getContributionScanner(contributionURL.getProtocol()); + if (scanner == null) { + File file = toFile(contributionURL); + if (file != null && file.isDirectory()) { + scanner = new DirectoryContributionScanner(contributionFactory); + } else { + scanner = new JarContributionScanner(contributionFactory); + } + } + + // Scan the contribution and list the artifacts contained in it + boolean contributionMetadata = false; + List<Artifact> artifacts = scanner.scan(contribution); + for (Artifact artifact : artifacts) { + // Add the deployed artifact model to the contribution + modelResolver.addModel(artifact, context); + + monitor.pushContext("Artifact: " + artifact.getURI()); + + Artifact oldArtifact = context.setArtifact(artifact); + try { + // Read each artifact + URL artifactLocationURL = null; + try { + artifactLocationURL = new URL(artifact.getLocation()); + } catch(MalformedURLException e) { + //ignore + } + + Object model = artifactProcessor.read(contributionURL, URI.create(artifact.getURI()), artifactLocationURL, context); + if (model != null) { + artifact.setModel(model); + + // Add the loaded model to the model resolver + modelResolver.addModel(model, context); + + // Merge contribution metadata into the contribution model + if (model instanceof ContributionMetadata) { + contributionMetadata = true; + ContributionMetadata c = (ContributionMetadata)model; + contribution.getImports().addAll(c.getImports()); + contribution.getExports().addAll(c.getExports()); + contribution.getDeployables().addAll(c.getDeployables()); + contribution.getExtensions().addAll(c.getExtensions()); + contribution.getAttributeExtensions().addAll(c.getAttributeExtensions()); + } + } + } finally { + monitor.popContext(); + context.setArtifact(oldArtifact); + } + } + + List<Artifact> contributionArtifacts = contribution.getArtifacts(); + contributionArtifacts.addAll(artifacts); + + // If no sca-contribution.xml file was provided then just consider + // all composites in the contribution as deployables + if (!contributionMetadata) { + for (Artifact artifact: artifacts) { + if (artifact.getModel() instanceof Composite) { + contribution.getDeployables().add((Composite)artifact.getModel()); + } + } + + // Add default contribution import and export + DefaultImport defaultImport = contributionFactory.createDefaultImport(); + defaultImport.setModelResolver(new DefaultModelResolver()); + contribution.getImports().add(defaultImport); + DefaultExport defaultExport = contributionFactory.createDefaultExport(); + contribution.getExports().add(defaultExport); + } else { + if (contribution.getDeployables().size() > 0) { + // Update the deployable Composite objects with the correct Composite object for the artifact + for (Artifact a : contribution.getArtifacts()) { + if (a.getModel() instanceof Composite) { + for (ListIterator<Composite> lit = contribution.getDeployables().listIterator(); lit.hasNext();) { + if (lit.next().getName().equals(((Composite)a.getModel()).getName())) { + lit.set((Composite)a.getModel()); + } + } + } + } + } + } + } finally { + monitor.popContext(); + context.setContribution(old); + } + + return contribution; + } + + /** + * A pre-resolution step, which is required for Contributions to handle the resolution of imports and exports so that + * at resolve time, imports can be followed to exports and anything exported that is required can be resolved on demand + * without the need to have already resolved the whole of the Contribution containing the export + * @param contribution - the Contribution + * @param resolver - the Resolver to use + * @throws ContributionResolveException + */ + public void preResolve(Contribution contribution, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + // Resolve the contribution model itself + ModelResolver contributionResolver = contribution.getModelResolver(); + contribution.setUnresolved(false); + contributionResolver.addModel(contribution, context); + + // Resolve Exports + resolveExports(contribution, contributionResolver, context); + // Resolve Imports + resolveImports(contribution, contributionResolver, context); + + preResolved = true; + } // end method preResolve + + public void resolve(Contribution contribution, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + + Monitor monitor = context.getMonitor(); + Contribution old = context.setContribution(contribution); + try { + monitor.pushContext("Contribution: " + contribution.getURI()); + + if( !preResolved ) preResolve( contribution, resolver, context); + ModelResolver contributionResolver = contribution.getModelResolver(); + + // Validate Java Exports: [JCI100007] A Java package that is specified on an export + // element MUST be contained within the contribution containing the export element. + for (Export export: contribution.getExports()) { + if (export instanceof JavaExport) { + boolean available = false; + String packageName = ((JavaExport)export).getPackage(); + for (Artifact artifact : contribution.getArtifacts()) { + if (packageName.equals(artifact.getURI().replace("/", "."))) + available = true; + } + if (! available) + throw new ContributionResolveException("[JCI100007] A Java package "+ packageName +" that is specified on an export " + + "element MUST be contained within the contribution containing the export element."); + } + } + + // Resolve all artifact models + for (Artifact artifact : contribution.getArtifacts()) { + Object model = artifact.getModel(); + if (model != null) { + Artifact oldArtifact = context.setArtifact(artifact); + try { + artifactProcessor.resolve(model, contributionResolver, context); + } catch (Throwable e) { + throw new ContributionResolveException(e); + } finally { + context.setArtifact(oldArtifact); + } + } + } + + // Resolve deployable composites + List<Composite> deployables = contribution.getDeployables(); + Artifact oldArtifact = context.setArtifact(contribution); + try { + for (int i = 0, n = deployables.size(); i < n; i++) { + Composite deployable = deployables.get(i); + Composite resolved = + (Composite)contributionResolver.resolveModel(Composite.class, deployable, context); + if (resolved != deployable) { + deployables.set(i, resolved); + } + } // end for + } finally { + context.setArtifact(oldArtifact); + } + } finally { + monitor.popContext(); + context.setContribution(old); + } // end try + } // end method resolve + + /** + * Resolves the Exports of the contribution + * @param contribution + * @param resolver + */ + private void resolveExports(Contribution contribution, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + for (Export export: contribution.getExports()) { + if (export instanceof DefaultExport) { + // Initialize the default export's resolver + export.setModelResolver(resolver); + } else { + extensionProcessor.resolve(export, resolver, context); + } // end if + } // end for + + } // end method resolveExports + + /** + * Resolves the Imports of the contribution + * @param contribution + * @param resolver + */ + private void resolveImports(Contribution contribution, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + for (Import import_: contribution.getImports()) { + extensionProcessor.resolve(import_, resolver, context); + } // end for + } // end method resolveImports + +} // end class ContributionContentProcessor diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java new file mode 100644 index 0000000000..f589c6b911 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java @@ -0,0 +1,79 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor.xml; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Extension; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXAttributeProcessor; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; + +/** + * A Policy Processor used for testing. + * + * @version $Rev$ $Date$ + */ +public class AnyAttributeProcessor extends BaseStAXArtifactProcessor implements StAXAttributeProcessor<Extension> { + + private AssemblyFactory assemblyFactory; + + public AnyAttributeProcessor(FactoryExtensionPoint modelFactories) { + this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + } + + public QName getArtifactType() { + return ExtensibleStAXAttributeProcessor.ANY_ATTRIBUTE; + } + + public Class<Extension> getModelType() { + return Extension.class; + } + + public Extension read(QName attributeName, XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException { + String attributeValue = reader.getAttributeValue(attributeName.getNamespaceURI(), attributeName.getLocalPart()); + Extension ext = assemblyFactory.createExtension(); + ext.setQName(attributeName); + ext.setAttribute(true); + ext.setValue(attributeValue); + return ext; + } + + public void write(Extension attributeExtension, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException { + writer.writeAttribute(attributeExtension.getQName().getPrefix(), + attributeExtension.getQName().getNamespaceURI(), + attributeExtension.getQName().getLocalPart(), + attributeExtension.getValue().toString()); //for extended attributes, we can assume values + // are just the string representation fo the attribute + } + + public void resolve(Extension model, ModelResolver modelResolver, ProcessorContext context) throws ContributionResolveException { + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java new file mode 100644 index 0000000000..db4feeec48 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java @@ -0,0 +1,96 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.processor.xml; + +import java.io.StringReader; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Extension; +import org.apache.tuscany.sca.common.xml.stax.StAXHelper; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; + +public class AnyElementProcessor implements StAXArtifactProcessor<Extension> { + private AssemblyFactory assemblyFactory; + private StAXHelper helper; + + public AnyElementProcessor(ExtensionPointRegistry extensionPoints, StAXArtifactProcessor<Object> extensionProcessor) { + FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + this.helper = StAXHelper.getInstance(extensionPoints); + } + + public QName getArtifactType() { + return ExtensibleStAXArtifactProcessor.ANY_ELEMENT; + } + + public Class<Extension> getModelType() { + return Extension.class; + } + + /** + * Reads the contetns of the unknown elements and generates a custom + * implementation of XMLStreamReader i.e. XMLEventsStreamReader + * + * @param reader + * @return + * @throws XMLStreamException + */ + public Extension read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException { + QName name = reader.getName(); + String xml = helper.saveAsString(reader); + Extension ext = assemblyFactory.createExtension(); + ext.setQName(name); + ext.setValue(xml); + + return ext; + } + + /** + * Writes unknown portions back to the writer + * + * @param model + * @param writer + */ + public void write(Extension model, XMLStreamWriter writer, ProcessorContext context) throws XMLStreamException { + Object value = model.getValue(); + if (!(value instanceof String)) { + return; + } + String xml = (String) value; + XMLStreamReader reader = helper.createXMLStreamReader(new StringReader(xml)); + // Position the reader to the root element + reader.nextTag(); + helper.save(reader, writer); + } + + public void resolve(Extension model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java new file mode 100644 index 0000000000..7d8f2ef1c8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java @@ -0,0 +1,129 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.lang.ref.WeakReference; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.contribution.Contribution; + +/** + * A weak reference to a class, which should be used to register classes + * with an ArtifactResolver and resolve these classes later. + * + * FIXME The core contribution model should not have dependencies on classes + * and ClassLoaders. This should move to the Java import support module. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class ClassReference implements Base { + + private WeakReference<Class<?>> clazz; + private String className; + private Contribution contributionContainingClass; + + /** + * Constructs a new ClassReference. + * + * @param clazz The class reference + */ + public ClassReference(Class<?> clazz) { + this.clazz = new WeakReference<Class<?>>(clazz); + this.className = clazz.getName(); + } + + /** + * Constructs a new ClassReference. + * + * @param className The class name + */ + public ClassReference(String className) { + this.className = className; + } + + /** + * Get the referenced class. + * + * @return The referenced class + */ + public Class<?> getJavaClass() { + if (clazz != null) { + return clazz.get(); + } else { + return null; + } + } + + /** + * Get the referenced class name. + * + * @return The class name + */ + public String getClassName() { + return className; + } + + public boolean isUnresolved() { + return clazz == null; + } + + public void setUnresolved(boolean unresolved) { + throw new IllegalStateException(); + } + + @Override + public int hashCode() { + return className.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof ClassReference) { + return className.equals(((ClassReference)obj).className); + } else { + return false; + } + } + } + + /** + * A Java class may reference a WSDL file via a JAXWS annotation. We need to resolve + * the WSDL file location in the context of the same contribution that holds the + * Java file. In order to do this we need to pass back the actual contribution that + * was used to resolve a Java class. It's possible that multiple contributions hold + * the same class so just scanning the artifacts in all the contribution is not good + * enough + * + * @return + */ + public Contribution getContributionContainingClass() { + return contributionContainingClass; + } + + public void setContributionContainingClass( + Contribution contributionContainingClass) { + this.contributionContainingClass = contributionContainingClass; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java new file mode 100644 index 0000000000..e17dd176a6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; + +/** + * A model resolver implementation that delegates to a list of model resolvers. + * + * @version $Rev$ $Date$ + */ +public class DefaultDelegatingModelResolver implements ModelResolver { + + private List<ModelResolver> resolvers; + + public DefaultDelegatingModelResolver(List<ModelResolver> resolvers) { + this.resolvers = resolvers; + } + + public void addModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + + //TODO optimize and cache results of the resolution later + + // Go over all resolvers + for (ModelResolver resolver: resolvers) { + + Object resolved = resolver.resolveModel(modelClass, unresolved, context); + + // Return the resolved model object + if (resolved instanceof Base) { + if (!((Base)resolved).isUnresolved()) { + return modelClass.cast(resolved); + } + } + } + + // Model object was not resolved + return unresolved; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java new file mode 100644 index 0000000000..7745253bba --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; + +/** + * A model resolver implementation that considers Exports in a list of contributions. + * + * @version $Rev$ $Date$ + */ +public class DefaultImportAllModelResolver implements ModelResolver { + + private Import import_; + private List<Contribution> contributions; + + public DefaultImportAllModelResolver(Import import_, List<Contribution> contributions) { + this.import_ = import_; + this.contributions = contributions; + } + + public void addModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + + //TODO optimize and cache results of the resolution later + + // Go over all available contributions + for (Contribution contribution : contributions) { + + // Go over all exports in the contribution + for (Export export : contribution.getExports()) { + + // If the export matches the export, try to resolve the model object + if (import_.match(export)) { + Object resolved = export.getModelResolver().resolveModel(modelClass, unresolved, context); + + // Return the resolved model object + if (resolved instanceof Base) { + if (!((Base)resolved).isUnresolved()) { + return modelClass.cast(resolved); + } + } + } + } + } + + // Model object was not resolved + return unresolved; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java new file mode 100644 index 0000000000..8a11cb42f8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; + +/** + * A model resolver implementation that delegates to a list of exports. + * + * @version $Rev$ $Date$ + */ +public class DefaultImportModelResolver implements ModelResolver { + + private List<Export> exports; + + public DefaultImportModelResolver(List<Export> exports) { + this.exports = exports; + } + + public void addModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + throw new IllegalStateException(); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + + //TODO optimize and cache results of the resolution later + + // Go over all exports + for (Export export: exports) { + + Object resolved = export.getModelResolver().resolveModel(modelClass, unresolved, context); + + // Return the resolved model object + if (resolved instanceof Base) { + if (!((Base)resolved).isUnresolved()) { + return modelClass.cast(resolved); + } + } + } + + // Model object was not resolved + return unresolved; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java new file mode 100644 index 0000000000..94b2fb0058 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java @@ -0,0 +1,89 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.DefaultImport; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; + +/** + * A default implementation of a model resolver based on a map. + * + * @version $Rev$ $Date$ + */ +public class DefaultModelResolver implements ModelResolver { + + private Contribution contribution; + private Map<Object, Object> map = new HashMap<Object, Object>(); + + public DefaultModelResolver() { + } + + public DefaultModelResolver(Contribution contribution, FactoryExtensionPoint modelFactories) { + this.contribution = contribution; + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else { + + // by default try and resolve through a default import + // if there is one. + if (contribution != null){ + for (Import _import : contribution.getImports()){ + if (_import instanceof DefaultImport){ + resolved = _import.getModelResolver().resolveModel(modelClass, unresolved, context); + if (resolved != unresolved){ + return modelClass.cast(resolved); + } + } + } + } + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved, ProcessorContext context) { + map.put(resolved, resolved); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + return map.remove(resolved); + } + + // FIXME: TUSCANY-2499: temporarily give access to the models to get the jms binding + // use of definitions.xml working while the definitions.xml processing is being refactored + public Map<Object, Object> getModels() { + return map; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java new file mode 100644 index 0000000000..a1eb85edca --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java @@ -0,0 +1,131 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.resolver; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; + + +/** + * The default implementation of a model resolver extension point. + * + * @version $Rev$ $Date$ + */ +public class DefaultModelResolverExtensionPoint implements ModelResolverExtensionPoint { + + private final Map<Class<?>, Class<? extends ModelResolver>> resolvers = new HashMap<Class<?>, Class<? extends ModelResolver>>(); + private Map<String, ServiceDeclaration> loadedResolvers; + private ExtensionPointRegistry registry; + + /** + * Constructs a new DefaultModelResolverExtensionPoint. + */ + public DefaultModelResolverExtensionPoint(ExtensionPointRegistry registry) { + this.registry = registry; + } + + public void addResolver(Class<?> modelType, Class<? extends ModelResolver> resolver) { + resolvers.put(modelType, resolver); + } + + public void removeResolver(Class<?> modelType) { + resolvers.remove(modelType); + } + + @SuppressWarnings("unchecked") + public Class<? extends ModelResolver> getResolver(Class<?> modelType) { + loadModelResolvers(); + + Class<?>[] classes = modelType.getInterfaces(); + for (Class<?> c : classes) { + Class<? extends ModelResolver> resolver = resolvers.get(c); + if (resolver == null) { + ServiceDeclaration resolverClass = loadedResolvers.get(c.getName()); + if (resolverClass != null) { + try { + return (Class<? extends ModelResolver>)resolverClass.loadClass(); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + } + } else { + return resolver; + } + } + + Class<? extends ModelResolver > resolver = resolvers.get(modelType); + if (resolver == null) { + ServiceDeclaration resolverClass = loadedResolvers.get(modelType.getName()); + if (resolverClass != null) { + try { + return (Class<? extends ModelResolver>)resolverClass.loadClass(); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + } + } + return resolver; + } + + /** + * Dynamically load model resolvers declared under META-INF/services + */ + private synchronized void loadModelResolvers() { + if (loadedResolvers != null) + return; + loadedResolvers = new HashMap<String, ServiceDeclaration>(); + + // Get the model resolver service declarations + Collection<ServiceDeclaration> modelResolverDeclarations; + try { + modelResolverDeclarations = registry.getServiceDiscovery().getServiceDeclarations(ModelResolver.class, true); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + List<ServiceDeclaration> list = new ArrayList<ServiceDeclaration>(modelResolverDeclarations); + + // Load model resolvers, add entries from lower ranking to higher ranking so that higher ranking ones override + // the map + for (int i = list.size() - 1; i >= 0; i--) { + ServiceDeclaration modelResolverDeclaration = list.get(i); + Map<String, String> attributes = modelResolverDeclaration.getAttributes(); + String model = attributes.get("model"); + // The model can be a list of interfaces so that one model resolver can be used + // to resolve different types of models + if (model != null) { + StringTokenizer tokenizer = new StringTokenizer(model); + while (tokenizer.hasMoreTokens()) { + String key = tokenizer.nextToken(); + loadedResolvers.put(key, modelResolverDeclaration); + } + + } + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java new file mode 100644 index 0000000000..72e4b03c7f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java @@ -0,0 +1,179 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; + +/** + * An implementation of an extensible model resolver which delegates to the + * proper resolver extension based on the class of the model to resolve. + * + * @version $Rev$ $Date$ + */ +public class ExtensibleModelResolver implements ModelResolver { + private final ModelResolverExtensionPoint resolverExtensions; + private final FactoryExtensionPoint modelFactories; + private final Contribution contribution; + private ModelResolver defaultResolver; + private final Map<Class<?>, ModelResolver> resolversByModelType = new HashMap<Class<?>, ModelResolver>(); + private final Map<Class<?>, ModelResolver> resolversByImplementationClass = new HashMap<Class<?>, ModelResolver>(); + private Map<Object, Object> map = new HashMap<Object, Object>(); + private Object lastUnresolved; + + /** + * Constructs an extensible model resolver + * + * @param resolverExtensions + * @param contribution + * @param modelFactories + */ + public ExtensibleModelResolver(Contribution contribution, + ModelResolverExtensionPoint resolverExtensions, + FactoryExtensionPoint modelFactories) { + this.contribution = contribution; + this.resolverExtensions = resolverExtensions; + this.modelFactories = modelFactories; + } + + /** + * Returns the proper resolver instance based on the interfaces of the model + * If one is not available on the registry, instantiate on demand + * + * @param modelType + * @return + */ + private ModelResolver getModelResolverInstance(Class<?> modelType) { + // Look up a model resolver instance for the model class or + // each implemented interface + Class<?>[] interfaces = modelType.getInterfaces(); + Class<?>[] classes = new Class<?>[interfaces.length + 1]; + classes[0] = modelType; + if (interfaces.length != 0) { + System.arraycopy(interfaces, 0, classes, 1, interfaces.length); + } + for (Class<?> c : classes) { + + // Look up an existing model resolver instance + ModelResolver resolverInstance = resolversByModelType.get(c); + if (resolverInstance != null) { + return resolverInstance; + } + + // We don't have an instance, lookup a model resolver class + // and instantiate it + Class<? extends ModelResolver> resolverClass = resolverExtensions.getResolver(c); + if (resolverClass != null) { + + // Construct the model resolver instance and cache it + resolverInstance = resolversByImplementationClass.get(resolverClass); + if (resolverInstance != null) { + resolversByModelType.put(c, resolverInstance); + return resolverInstance; + } + try { + Constructor<? extends ModelResolver> constructor = + resolverClass + .getConstructor(new Class[] {Contribution.class, FactoryExtensionPoint.class}); + if (constructor != null) { + + resolverInstance = constructor.newInstance(contribution, modelFactories); + resolversByImplementationClass.put(resolverClass, resolverInstance); + resolversByModelType.put(c, resolverInstance); + return resolverInstance; + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + } + + return null; + } + + public void addModel(Object resolved, ProcessorContext context) { + ModelResolver resolver = getModelResolverInstance(resolved.getClass()); + if (resolver != null) { + resolver.addModel(resolved, context); + } else { + map.put(resolved, resolved); + } + } + + public Object removeModel(Object resolved, ProcessorContext context) { + ModelResolver resolver = getModelResolverInstance(resolved.getClass()); + if (resolver != null) { + return resolver.removeModel(resolved, context); + } else { + return map.remove(resolved); + } + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + // Protect against dependency cycles causing infinite recursion + // Save the current unresolved object and check later if we are trying + // to resolve the same object again + if (unresolved == lastUnresolved) { + return unresolved; + } + lastUnresolved = unresolved; + + ModelResolver resolver = getModelResolverInstance(unresolved.getClass()); + if (resolver != null) { + Object resolved = resolver.resolveModel(modelClass, unresolved, context); + if (resolved != null && resolved != unresolved) { + lastUnresolved = null; + return modelClass.cast(resolved); + } + } else { + //FIXME Remove this default resolver, this is currently used to resolve policy declarations + // but they should be handled by the contribution import/export mechanism instead of this + // defaultResolver hack. + if (defaultResolver != null) { + Object resolved = defaultResolver.resolveModel(modelClass, unresolved, context); + if (resolved != null && resolved != unresolved) { + lastUnresolved = null; + return modelClass.cast(resolved); + } + } + + Object resolved = map.get(unresolved); + if (resolved != null) { + // Return the resolved object + lastUnresolved = null; + return modelClass.cast(resolved); + } + } + + return unresolved; + } + + // FIXME: TUSCANY-2499: temporarily give access to the defaultResolver to get the jms binding + // use of definitions.xml working while the definitions.xml processing is being refactored + public ModelResolver getDefaultModelResolver() { + return defaultResolver; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java new file mode 100644 index 0000000000..c0267261f4 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; + +/** + * A model resolver, responsible for resolving models in the scope of an + * SCA contribution. + * + * SCA Assemblies reference artifacts of a wide variety of types. These + * include: + * <ul> + * <li> Reference from one SCA composite to another SCA composite + * <li> Reference to PolicySet files + * <li> Reference to interface definition files, either WSDL or Java interfaces + * <li> Reference to XSD files + * <li> Reference to any of a wide variety of implementation artifact files, + * including Java classes, BPEL scripts, C++ DLLs and classes, PHP scripts + * </ul> + * + * In the SCA assemblies, these various artifacts are referenced using either + * QNames or logical URIs. Model resolvers are used to resolve these references + * and get the in-memory models representing the referenced artifacts. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface ModelResolver { + + /** + * Resolve the model representing an artifact. + * + * @param modelClass the type of artifact + * @param unresolved the unresolved model + * @param context The context + * @return the resolved model + */ + <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context); + + /** + * Add a resolved model. + * + * @param resolved The model + * @param context + */ + void addModel(Object resolved, ProcessorContext context); + + /** + * Remove a resolved model. + * + * @param resolved + * @param context + * @return The removed model, or null if the model was not removed + */ + Object removeModel(Object resolved, ProcessorContext context); + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java new file mode 100644 index 0000000000..4a25059792 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + + +/** + * An extension point for model resolvers + * + * @version $Rev$ $Date$ + */ +public interface ModelResolverExtensionPoint { + + /** + * Register a model resolver class using the model type as the key + * + * @param modelType The model type + * @param resolver The model resolver Class + */ + void addResolver(Class<?> modelType, Class <? extends ModelResolver> resolver); + + /** + * Remove the model resolver class for a specific model type + * + * @param modelType The model type + */ + void removeResolver(Class<?> modelType); + + /** + * Retrieve a model resolver class for a specific model type + * + * @param modelType The model artifact type + * @return The model resolver Class + */ + Class <? extends ModelResolver> getResolver(Class<?> modelType); +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java new file mode 100644 index 0000000000..bcf146cbfe --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java @@ -0,0 +1,46 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +/** + * Extension to assembly model implementations to provide a model resolver. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface ResolverExtension { + + /** + * Returns the model resolver for the models representing the artifacts + * visible in the scope of this contribution. + * + * @return The model resolver + */ + ModelResolver getModelResolver(); + + /** + * Sets the model resolver for the models representing the artifacts + * visible in the scope of this contribution. + * + * @param modelResolver The model resolver + */ + void setModelResolver(ModelResolver modelResolver); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java new file mode 100644 index 0000000000..dfe8f08719 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java @@ -0,0 +1,103 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.net.URL; + +/** + * A resource URL, which should be used to register resources + * with an ArtifactResolver and resolve these resources later. + * + * FIXME Don't use as its deprecated, use Artifact instead. + * + * @version $Rev$ $Date$ + */ +@Deprecated +public class ResourceReference { + + private URL resourceURL; + private String resourceName; + + /** + * Constructs a new ResourceReference. + * + * @param resourceName Name of resource + * @param resourceURL The resource URL + */ + public ResourceReference(String resourceName, URL resourceURL) { + this.resourceURL = resourceURL; + this.resourceName = resourceName; + } + + /** + * Constructs a new ResourceReference. + * + * @param resourceName Name of resource + */ + public ResourceReference(String resourceName) { + this.resourceName = resourceName; + } + + /** + * Get the resource URL. + * + * @return The resource URL + */ + public URL getResource() { + return resourceURL; + } + + /** + * Get the resource name. + * + * @return The resource name + */ + public String getResourceName() { + return resourceName; + } + + /** + * Returns true if the resource reference is unresolved. + * + * @return Whether or not the resource has been resolved + */ + public boolean isUnresolved() { + return resourceURL == null; + } + + @Override + public int hashCode() { + return resourceName.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof ResourceReference) { + return resourceName.equals(((ResourceReference)obj).resourceName); + } else { + return false; + } + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java new file mode 100644 index 0000000000..91697111af --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java @@ -0,0 +1,55 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.scanner; + +import java.io.IOException; +import java.util.List; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; + +/** + * Interface for contribution package scanners + * + * Contribution scanners understand the format of the contribution and how to get the + * artifacts in the contribution. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface ContributionScanner { + + /** + * Returns the type of package supported by this package scanner. + * + * @return the package type + */ + String getContributionType(); + + /** + * Returns a list of artifacts in the contribution. + * + * @param contribution Contribution URL + * @return List of artifact populated with URIs and location URL + * @throws ContributionReadException + * @throws IOException + */ + List<Artifact> scan(Contribution contribution) throws ContributionReadException; +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java new file mode 100644 index 0000000000..1ca9def4ea --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java @@ -0,0 +1,50 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.scanner; + +/** + * An extension point for contribution scanners + * + * @version $Rev$ $Date$ + */ +public interface ContributionScannerExtensionPoint { + + /** + * Add a ContributionScanner using the contribution type as the key. + * + * @param scanner The contribution scanner + */ + void addContributionScanner(ContributionScanner scanner); + + /** + * Remove a ContributionScanner. + * + * @param scanner The contribution scanner + */ + void removeContributionScanner(ContributionScanner scanner); + + /** + * Returns the ContributionScanner for the given contribution type. + * + * @param contributionType The contribution type + * @return The contribution scanner + */ + ContributionScanner getContributionScanner(String contributionType); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java new file mode 100644 index 0000000000..c5aed5ccd3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java @@ -0,0 +1,131 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.scanner; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; + +/** + * Default implementation of a contribution scanner extension point. + * + * @version $Rev$ $Date$ + */ +public class DefaultContributionScannerExtensionPoint implements ContributionScannerExtensionPoint { + + private Map<String, ContributionScanner> scanners = new HashMap<String, ContributionScanner>(); + private boolean loaded; + private ExtensionPointRegistry registry; + + public DefaultContributionScannerExtensionPoint(ExtensionPointRegistry registry) { + this.registry = registry; + } + + public void addContributionScanner(ContributionScanner scanner) { + scanners.put(scanner.getContributionType(), scanner); + } + + public void removeContributionScanner(ContributionScanner scanner) { + scanners.remove(scanner.getContributionType()); + } + + public ContributionScanner getContributionScanner(String contentType) { + loadScanners(); + return scanners.get(contentType); + } + + private synchronized void loadScanners() { + if (loaded) + return; + + // Get the scanner service declarations + Collection<ServiceDeclaration> scannerDeclarations; + try { + scannerDeclarations = registry.getServiceDiscovery().getServiceDeclarations(ContributionScanner.class.getName()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + for (ServiceDeclaration scannerDeclaration: scannerDeclarations) { + Map<String, String> attributes = scannerDeclaration.getAttributes(); + + // Load a URL artifact scanner + String contributionType = attributes.get("type"); + + // Create a scanner wrapper and register it + ContributionScanner scanner = new LazyContributionScanner(registry, contributionType, scannerDeclaration); + addContributionScanner(scanner); + } + + loaded = true; + } + + /** + * A facade for contribution scanners. + */ + private static class LazyContributionScanner implements ContributionScanner { + private ExtensionPointRegistry registry; + private ServiceDeclaration scannerDeclaration; + private String contributionType; + private ContributionScanner scanner; + private ContributionFactory contributionFactory; + + private LazyContributionScanner(ExtensionPointRegistry registry, String contributionType, ServiceDeclaration scannerDeclaration) { + this.registry = registry; + this.scannerDeclaration = scannerDeclaration; + this.contributionType = contributionType; + + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.contributionFactory = factories.getFactory(ContributionFactory.class); + } + + public List<Artifact> scan(Contribution contributionSourceURL) throws ContributionReadException { + return getScanner().scan(contributionSourceURL); + } + + public String getContributionType() { + return contributionType; + } + + private ContributionScanner getScanner() { + if (scanner == null) { + try { + Class<ContributionScanner> scannerClass = (Class<ContributionScanner>)scannerDeclaration.loadClass(); + Constructor<ContributionScanner> constructor = scannerClass.getConstructor(ContributionFactory.class); + scanner = constructor.newInstance(contributionFactory); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return scanner; + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java new file mode 100644 index 0000000000..4a064c8fa9 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java @@ -0,0 +1,173 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.scanner.impl; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.PackageType; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.scanner.ContributionScanner; + +/** + * Folder contribution processor. + * + * @version $Rev$ $Date$ + */ +public class DirectoryContributionScanner implements ContributionScanner { + private static final Logger logger = Logger.getLogger(DirectoryContributionScanner.class.getName()); + + private ContributionFactory contributionFactory; + + public DirectoryContributionScanner(ContributionFactory contributionFactory) { + this.contributionFactory = contributionFactory; + } + + public String getContributionType() { + return PackageType.FOLDER; + } + + public List<Artifact> scan(Contribution contribution) throws ContributionReadException { + File directory = directory(contribution); + List<Artifact> artifacts = new ArrayList<Artifact>(); + List<String> artifactURIs = scanContributionArtifacts(contribution); + for(String uri : artifactURIs) { + try { + File file = new File(directory, uri); + + Artifact artifact = contributionFactory.createArtifact(); + artifact.setURI(uri); + artifact.setLocation(file.toURI().toURL().toString()); + + artifacts.add(artifact); + } catch (MalformedURLException e) { + throw new ContributionReadException(e); + } + } + + contribution.getTypes().add(getContributionType()); + return artifacts; + } + + + /** + * Scan the contribution to retrieve all artifact uris + * + * @param contribution + * @return + * @throws ContributionReadException + */ + private List<String> scanContributionArtifacts(Contribution contribution) throws ContributionReadException { + File directory = directory(contribution); + List<String> artifacts = new ArrayList<String>(); + // [rfeng] There are cases that the folder contains symbolic links that point to the same physical directory + Set<File> visited = new HashSet<File>(); + try { + traverse(artifacts, directory, directory, visited); + } catch (IOException e) { + throw new ContributionReadException(e); + } + + return artifacts; + } + + /** + * Recursively traverse a root directory + * + * @param fileList + * @param file + * @param root + * @param visited The visited directories + * @throws IOException + */ + private static void traverse(List<String> fileList, File file, File root, Set<File> visited) throws IOException { + + //TUSCANY-3667 - Google add some private directories when you deploy your application + //to GAE and trying to execute file IO operations on it's contents fails with AccessControlException + try { + if (file.isFile()) { + fileList.add(root.toURI().relativize(file.toURI()).toString()); + } else if (file.isDirectory()) { + File dir = file.getCanonicalFile(); + if (!visited.contains(dir)) { + // [rfeng] Add the canonical file into the visited set to avoid duplicate navigation of directories + // following the symbolic links + visited.add(dir); + String uri = root.toURI().relativize(file.toURI()).toString(); + if (uri.endsWith("/")) { + uri = uri.substring(0, uri.length() - 1); + } + fileList.add(uri); + + File[] files = file.listFiles(); + for (File f : files) { + if (!f.getName().startsWith(".")) { + traverse(fileList, f, root, visited); + } + } + } + } + } catch (AccessControlException e) { + //TUSCANY-3667 - Log the AccessControlException error and continue without processing the file/directory + logger.log(Level.WARNING, "Error traversing file:" + file.getPath()); + } + + } + + /** + * Get the contribution location as a file + * + * @param contribution + * @return + * @throws ContributionReadException + */ + private File directory(Contribution contribution) throws ContributionReadException { + File file; + URI uri = null; + try { + uri = new URI(contribution.getLocation()); + file = new File(uri); + } catch (URISyntaxException e) { + throw new ContributionReadException(e); + } catch(IllegalArgumentException e) { + // Hack for file:./a.txt or file:../a/c.wsdl + return new File(uri.getPath()); + } + if (!file.exists() || !file.isDirectory()) { + throw new ContributionReadException(contribution.getLocation()); + } + return file; + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java new file mode 100644 index 0000000000..25be92c310 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java @@ -0,0 +1,143 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.scanner.impl; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +import org.apache.tuscany.sca.common.java.io.IOHelper; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.PackageType; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.scanner.ContributionScanner; + +/** + * JAR Contribution processor. + * + * @version $Rev$ $Date$ + */ +public class JarContributionScanner implements ContributionScanner { + private ContributionFactory contributionFactory; + + public JarContributionScanner(ContributionFactory contributionFactory) { + this.contributionFactory = contributionFactory; + } + + public String getContributionType() { + return PackageType.JAR; + } + + public List<Artifact> scan(Contribution contribution) throws ContributionReadException { + + // Assume the URL references a JAR file + try { + URL url = new URL(contribution.getLocation()); + JarInputStream jar = new JarInputStream(IOHelper.openStream(url)); + try { + Set<String> names = new HashSet<String>(); + while (true) { + JarEntry entry = jar.getNextJarEntry(); + if (entry == null) { + // EOF + break; + } + + String name = entry.getName(); + if (name.length() != 0 && !name.startsWith(".")) { + + // Trim trailing / + if (name.endsWith("/")) { + name = name.substring(0, name.length() - 1); + } + + // Add the entry name + if (!names.contains(name)) { + names.add(name); + + // Add parent folder names to the list too + for (;;) { + int s = name.lastIndexOf('/'); + if (s == -1) { + name = ""; + } else { + name = name.substring(0, s); + } + if (name.length() != 0 && !names.contains(name)) { + names.add(name); + } else { + break; + } + } + } + } + } + + // Return list of artifacts + List<Artifact> artifacts = new ArrayList<Artifact>(); + for(String uri : names) { + Artifact artifact = contributionFactory.createArtifact(); + artifact.setURI(uri); + artifact.setLocation(getArtifactURL(contribution, uri).toString()); + + artifacts.add(artifact); + } + + contribution.getTypes().add(getContributionType()); + return artifacts; + + } finally { + jar.close(); + } + } catch (IOException e) { + throw new ContributionReadException(e); + } + } + + /** + * Produces a location URL for a given artifact in the contribution + * + * @param contribution + * @param artifact + * @return + * @throws ContributionReadException + */ + private static URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException { + try { + URL url; + if (contribution.toString().startsWith("jar:")) { + url = new URL(new URL(contribution.getLocation()), artifact.toString()); + } else { + url = new URL("jar:" + contribution.getLocation() + "!/" + artifact); + } + return url; + } catch (MalformedURLException e) { + throw new ContributionReadException(e); + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java new file mode 100644 index 0000000000..0ad3ecbd4d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java @@ -0,0 +1,48 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.xml; + +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * URLArtifactProcessor that handles sca-contribution-generated.xml files. + * + * @version $Rev$ $Date$ + */ +public class ContributionGeneratedMetadataDocumentProcessor extends ContributionMetadataDocumentProcessor { + + public ContributionGeneratedMetadataDocumentProcessor(XMLInputFactory inputFactory, + StAXArtifactProcessor staxProcessor) { + super(inputFactory, staxProcessor); + } + + public ContributionGeneratedMetadataDocumentProcessor(FactoryExtensionPoint modelFactories, + StAXArtifactProcessor staxProcessor) { + super(modelFactories, staxProcessor); + } + + @Override + public String getArtifactType() { + return "/META-INF/sca-contribution-generated.xml"; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java new file mode 100644 index 0000000000..30220901a0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java @@ -0,0 +1,127 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.common.java.io.IOHelper; +import org.apache.tuscany.sca.contribution.ContributionMetadata; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * URLArtifactProcessor that handles sca-contribution.xml files. + * + * @version $Rev$ $Date$ + */ +public class ContributionMetadataDocumentProcessor implements URLArtifactProcessor<ContributionMetadata>{ + private final StAXArtifactProcessor staxProcessor; + private final XMLInputFactory inputFactory; + + public ContributionMetadataDocumentProcessor(XMLInputFactory inputFactory, + StAXArtifactProcessor staxProcessor) { + this.inputFactory = inputFactory; + this.staxProcessor = staxProcessor; + } + + public ContributionMetadataDocumentProcessor(FactoryExtensionPoint modelFactories, + StAXArtifactProcessor staxProcessor) { + this.inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class); + this.staxProcessor = staxProcessor; + } + + public String getArtifactType() { + return "/META-INF/sca-contribution.xml"; + } + + public Class<ContributionMetadata> getModelType() { + return ContributionMetadata.class; + } + + public ContributionMetadata read(URL contributionURL, URI uri, URL url, ProcessorContext context) throws ContributionReadException { + InputStream urlStream = null; + try { + + // Create a stream reader + urlStream = IOHelper.openStream(url); + XMLStreamReader reader = inputFactory.createXMLStreamReader(url.toString(), urlStream); + ValidatingXMLInputFactory.setMonitor(reader, context.getMonitor()); + + reader.nextTag(); + + // Read the contribution model + ContributionMetadata contribution = (ContributionMetadata)staxProcessor.read(reader, context); + + return contribution; + + } catch (XMLStreamException e) { + ContributionReadException ex = new ContributionReadException(e); + error(context.getMonitor(), "XMLStreamException", inputFactory, ex); + throw ex; + } catch (IOException e) { + ContributionReadException ex = new ContributionReadException(e); + error(context.getMonitor(), "IOException", inputFactory, ex); + throw ex; + } finally { + try { + if (urlStream != null) { + urlStream.close(); + urlStream = null; + } + } catch (IOException ioe) { + //ignore + } + } + } + + public void resolve(ContributionMetadata contribution, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + staxProcessor.resolve(contribution, resolver, context); + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-xml-validation-messages", Severity.ERROR, model, message, ex); + monitor.problem(problem); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java new file mode 100644 index 0000000000..823684f422 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java @@ -0,0 +1,270 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.contribution.xml; + +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ContributionMetadata; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.java.JavaImport; +import org.apache.tuscany.sca.contribution.java.JavaExport; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Processor for contribution metadata + * + * @version $Rev$ $Date$ + */ +public class ContributionMetadataProcessor extends BaseStAXArtifactProcessor implements + StAXArtifactProcessor<ContributionMetadata> { + private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200912"; + + private static final QName CONTRIBUTION_QNAME = new QName(SCA11_NS, "contribution"); + private static final QName DEPLOYABLE_QNAME = new QName(SCA11_NS, "deployable"); + + private final AssemblyFactory assemblyFactory; + private final ContributionFactory contributionFactory; + private final StAXArtifactProcessor<Object> extensionProcessor; + private final StAXAttributeProcessor<Object> attributeProcessor; + + + public ContributionMetadataProcessor(FactoryExtensionPoint modelFactories, + StAXArtifactProcessor<Object> extensionProcessor, + StAXAttributeProcessor<Object> attributeProcessor) { + this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + this.contributionFactory = modelFactories.getFactory(ContributionFactory.class); + this.extensionProcessor = extensionProcessor; + this.attributeProcessor = attributeProcessor; + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), + "contribution-xml-validation-messages", + Severity.ERROR, + model, + message, + (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = + monitor.createProblem(this.getClass().getName(), "contribution-xml-validation-messages", Severity.ERROR, + model, message, ex); + monitor.problem(problem); + } + } + + public QName getArtifactType() { + return CONTRIBUTION_QNAME; + } + + public Class<ContributionMetadata> getModelType() { + return ContributionMetadata.class; + } + + public ContributionMetadata read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException { + ContributionMetadata contribution = null; + QName name = null; + + try { + while (reader.hasNext()) { + int event = reader.getEventType(); + switch (event) { + case START_ELEMENT: + name = reader.getName(); + + if (CONTRIBUTION_QNAME.equals(name)) { + + // Read <contribution> + contribution = this.contributionFactory.createContributionMetadata(); + contribution.setSpecVersion(SCA11_NS); + contribution.setUnresolved(true); + readExtendedAttributes(reader, contribution, attributeProcessor, assemblyFactory, context); + + } else if (DEPLOYABLE_QNAME.equals(name)) { + + // Read <deployable> + QName compositeName = getQName(reader, "composite"); + if (compositeName == null) { + error(context.getMonitor(), "AttributeCompositeMissing", reader); + //throw new ContributionReadException("Attribute 'composite' is missing"); + } else { + if (contribution != null) { + Composite composite = assemblyFactory.createComposite(); + composite.setName(compositeName); + composite.setUnresolved(true); + contribution.getDeployables().add(composite); + } + } + } else { + + // Read an extension element + Object extension = extensionProcessor.read(reader, context); + if (extension != null && contribution != null) { + if (extension instanceof Import) { + // The value of the @package attribute on the <import.java/> element MUST be + // unique across all other <import.java/> elements within the contribution. + if (extension instanceof JavaImport) { + for (Import imports : contribution.getImports()) { + if (imports instanceof JavaImport) { + if (((JavaImport)extension).getPackage().equals(((JavaImport) imports).getPackage())) { + error(context.getMonitor(), "DuplicateJavaImports", reader); + } + } + } + } + contribution.getImports().add((Import)extension); + } else if (extension instanceof Export) { + // The value of the @package attribute on the <export.java/> element MUST be + // unique across all other <export.java/> elements within the contribution. + if (extension instanceof JavaExport) { + for (Export exports : contribution.getExports()) { + if (exports instanceof JavaExport) { + if (((JavaExport)extension).getPackage().equals(((JavaExport) exports).getPackage())) { + error(context.getMonitor(), "DuplicateJavaExports", reader); + } + } + } + } + contribution.getExports().add((Export)extension); + } else { + contribution.getExtensions().add(extension); + } + } + } + break; + + case XMLStreamConstants.END_ELEMENT: + if (CONTRIBUTION_QNAME.equals(reader.getName())) { + return contribution; + } + break; + } + + //Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + } catch (XMLStreamException e) { + ContributionReadException ex = new ContributionReadException(e); + error(context.getMonitor(), "XMLStreamException", reader, ex); + } + + return contribution; + } + + public void write(ContributionMetadata contribution, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, + XMLStreamException { + + // Write <contribution> + writeStartDocument(writer, CONTRIBUTION_QNAME.getNamespaceURI(), CONTRIBUTION_QNAME.getLocalPart()); + writeExtendedAttributes(writer, contribution, attributeProcessor, context); + + // Write <import> + for (Import imp : contribution.getImports()) { + extensionProcessor.write(imp, writer, context); + } + + // Write <export> + for (Export export : contribution.getExports()) { + extensionProcessor.write(export, writer, context); + } + + // Write <deployable> + for (Composite deployable : contribution.getDeployables()) { + writeStart(writer, + DEPLOYABLE_QNAME.getNamespaceURI(), + DEPLOYABLE_QNAME.getLocalPart(), + new XAttr("composite", deployable.getName())); + writeEnd(writer); + } + + writeEndDocument(writer); + } + + public void resolve(ContributionMetadata contribution, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + + // Resolve imports and exports + for (Export export : contribution.getExports()) { + extensionProcessor.resolve(export, resolver, context); + } + for (Import import_ : contribution.getImports()) { + extensionProcessor.resolve(import_, resolver, context); + } + + // Resolve deployable composites + List<Composite> deployables = contribution.getDeployables(); + for (int i = 0, n = deployables.size(); i < n; i++) { + Composite deployable = deployables.get(i); + Composite resolved = (Composite)resolver.resolveModel(Composite.class, deployable, context); + if (resolved != deployable) { + deployables.set(i, resolved); + } + } + + for (Object ext : contribution.getExtensions()) { + extensionProcessor.resolve(ext, resolver, context); + } + + contribution.setUnresolved(false); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java new file mode 100644 index 0000000000..916630939e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java @@ -0,0 +1,73 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.contribution.xml; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; + +/** + * A Model Resolver for Contribution models. + * + * @version $Rev$ $Date$ + */ +public class ContributionModelResolver implements ModelResolver { + + private Map<String, Contribution> map = new HashMap<String, Contribution>(); + + public ContributionModelResolver(Contribution contribution, FactoryExtensionPoint modelFactories) { + } + + public void addModel(Object resolved, ProcessorContext context) { + Contribution contribution = (Contribution)resolved; + map.put(contribution.getURI(), contribution); + } + + public Object removeModel(Object resolved, ProcessorContext context) { + return map.remove(((Contribution)resolved).getURI()); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { + + // Lookup a contribution for the given URI + String uri = ((Contribution)unresolved).getURI(); + if (uri != null) { + Contribution resolved = (Contribution) map.get(uri); + if (resolved != null) { + return modelClass.cast(resolved); + } + return unresolved; + } else { + + // If no URI was specified, just return the first contribution + if (!map.isEmpty()) { + Contribution resolved = map.values().iterator().next(); + return modelClass.cast(resolved); + } else { + return unresolved; + } + } + } + +} |