├── src
├── test
│ ├── test-data
│ │ ├── unhandled.conf
│ │ ├── realm-syntax.conf
│ │ ├── early-import.conf
│ │ ├── dupe-main.conf
│ │ ├── a.jar
│ │ ├── b.jar
│ │ ├── c.jar
│ │ ├── d.jar
│ │ ├── b_old.jar
│ │ ├── nested.jar
│ │ ├── deadlock.jar
│ │ ├── valid-launch.conf
│ │ ├── circular-0.1.jar
│ │ ├── dupe-realm.conf
│ │ ├── valid-launch-exitCode.conf
│ │ ├── component0-1.0.jar
│ │ ├── component1-1.0.jar
│ │ ├── component2-1.0.jar
│ │ ├── component3-1.0.jar
│ │ ├── component4-1.0.jar
│ │ ├── component5-1.0.jar
│ │ ├── component5-2.0.jar
│ │ ├── resources
│ │ │ ├── werkflow.jar
│ │ │ └── classworlds.conf
│ │ ├── from-from-0.0.1-from-load-import.jar
│ │ ├── launch-noclass.conf
│ │ ├── valid-enh-launch.conf
│ │ ├── valid-enh-launch-exitCode.conf
│ │ ├── launch-nomethod.conf
│ │ ├── optionally-nonexistent.conf
│ │ ├── optionally-existent.conf
│ │ ├── inheritance.conf
│ │ ├── set-using-missing.conf
│ │ ├── a.properties
│ │ ├── nested.properties
│ │ ├── valid.conf
│ │ ├── valid-from-from-from.conf
│ │ ├── set-using-existent.conf
│ │ ├── set-using-existent.properties
│ │ └── set-using-nonexistent.conf
│ └── java
│ │ └── org
│ │ └── codehaus
│ │ └── plexus
│ │ └── classworlds
│ │ ├── AbstractClassWorldsTestCase.java
│ │ ├── UrlUtilsTest.java
│ │ ├── TestUtil.java
│ │ ├── launcher
│ │ ├── ConfigurationParserTest.java
│ │ ├── LauncherTest.java
│ │ └── ConfiguratorTest.java
│ │ ├── ClassView.java
│ │ ├── strategy
│ │ └── StrategyTest.java
│ │ ├── realm
│ │ ├── FilteredClassRealmTest.java
│ │ ├── EntryTest.java
│ │ └── DefaultClassRealmTest.java
│ │ └── ClassWorldTest.java
├── main
│ └── java
│ │ └── org
│ │ └── codehaus
│ │ ├── plexus
│ │ └── classworlds
│ │ │ ├── ClassWorldListener.java
│ │ │ ├── strategy
│ │ │ ├── StrategyFactory.java
│ │ │ ├── Strategy.java
│ │ │ ├── AbstractStrategy.java
│ │ │ ├── SelfFirstStrategy.java
│ │ │ ├── ParentFirstStrategy.java
│ │ │ └── OsgiBundleStrategy.java
│ │ │ ├── launcher
│ │ │ ├── ConfigurationException.java
│ │ │ ├── ConfigurationHandler.java
│ │ │ └── Configurator.java
│ │ │ ├── UrlUtils.java
│ │ │ ├── realm
│ │ │ ├── NoSuchRealmException.java
│ │ │ ├── DuplicateRealmException.java
│ │ │ ├── FilteredClassRealm.java
│ │ │ └── Entry.java
│ │ │ ├── ClassWorldException.java
│ │ │ └── ClassWorld.java
│ │ └── classworlds
│ │ ├── BytesURLConnection.java
│ │ ├── BytesURLStreamHandler.java
│ │ ├── Launcher.java
│ │ ├── ClassWorld.java
│ │ ├── ConfiguratorAdapter.java
│ │ ├── ConfigurationException.java
│ │ ├── ClassWorldAdapter.java
│ │ ├── NoSuchRealmException.java
│ │ ├── DuplicateRealmException.java
│ │ ├── ClassWorldException.java
│ │ ├── ClassWorldReverseAdapter.java
│ │ ├── ClassRealm.java
│ │ ├── ClassRealmReverseAdapter.java
│ │ ├── ClassRealmAdapter.java
│ │ ├── Configurator.java
│ │ └── DefaultClassRealm.java
└── site
│ ├── site.xml
│ └── xdoc
│ ├── index.xml
│ ├── apiusage.xml
│ └── launcher.xml
├── .github
├── release-drafter.yml
├── workflows
│ ├── release-drafter.yml
│ └── maven.yml
└── dependabot.yml
├── .gitignore
├── README.md
├── LICENSE-Codehaus.txt
├── pom.xml
└── LICENSE.txt
/src/test/test-data/unhandled.conf:
--------------------------------------------------------------------------------
1 |
2 | foo
3 |
--------------------------------------------------------------------------------
/src/test/test-data/realm-syntax.conf:
--------------------------------------------------------------------------------
1 |
2 | [foo
3 | ]
4 |
--------------------------------------------------------------------------------
/src/test/test-data/early-import.conf:
--------------------------------------------------------------------------------
1 |
2 | import org.xml.sax from root
3 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | _extends: .github
2 | tag-template: plexus-classworlds-$NEXT_MINOR_VERSION
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .project
3 | .classpath
4 | .settings/
5 | bin
6 | .idea
7 | *.iml
8 | .java-version
9 |
--------------------------------------------------------------------------------
/src/test/test-data/dupe-main.conf:
--------------------------------------------------------------------------------
1 |
2 | main is com.werken.Foo from foo
3 | main is com.werken.Bar from bar
4 |
--------------------------------------------------------------------------------
/src/test/test-data/a.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/a.jar
--------------------------------------------------------------------------------
/src/test/test-data/b.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/b.jar
--------------------------------------------------------------------------------
/src/test/test-data/c.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/c.jar
--------------------------------------------------------------------------------
/src/test/test-data/d.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/d.jar
--------------------------------------------------------------------------------
/src/test/test-data/b_old.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/b_old.jar
--------------------------------------------------------------------------------
/src/test/test-data/nested.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/nested.jar
--------------------------------------------------------------------------------
/src/test/test-data/deadlock.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/deadlock.jar
--------------------------------------------------------------------------------
/src/test/test-data/valid-launch.conf:
--------------------------------------------------------------------------------
1 |
2 | main is a.A from app
3 |
4 | [app]
5 | load ${basedir}/src/test/test-data/a.jar
6 |
--------------------------------------------------------------------------------
/src/test/test-data/circular-0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/circular-0.1.jar
--------------------------------------------------------------------------------
/src/test/test-data/dupe-realm.conf:
--------------------------------------------------------------------------------
1 |
2 | [cheese]
3 |
4 | [dupe.realm]
5 |
6 | [potatoes]
7 |
8 | [dupe.realm]
9 |
10 |
--------------------------------------------------------------------------------
/src/test/test-data/valid-launch-exitCode.conf:
--------------------------------------------------------------------------------
1 |
2 | main is a.Aa from app
3 |
4 | [app]
5 | load ${basedir}/src/test/test-data/a.jar
6 |
--------------------------------------------------------------------------------
/src/test/test-data/component0-1.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/component0-1.0.jar
--------------------------------------------------------------------------------
/src/test/test-data/component1-1.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/component1-1.0.jar
--------------------------------------------------------------------------------
/src/test/test-data/component2-1.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/component2-1.0.jar
--------------------------------------------------------------------------------
/src/test/test-data/component3-1.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/component3-1.0.jar
--------------------------------------------------------------------------------
/src/test/test-data/component4-1.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/component4-1.0.jar
--------------------------------------------------------------------------------
/src/test/test-data/component5-1.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/component5-1.0.jar
--------------------------------------------------------------------------------
/src/test/test-data/component5-2.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/component5-2.0.jar
--------------------------------------------------------------------------------
/src/test/test-data/resources/werkflow.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/resources/werkflow.jar
--------------------------------------------------------------------------------
/src/test/test-data/from-from-0.0.1-from-load-import.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codehaus-plexus/plexus-classworlds/HEAD/src/test/test-data/from-from-0.0.1-from-load-import.jar
--------------------------------------------------------------------------------
/src/test/test-data/launch-noclass.conf:
--------------------------------------------------------------------------------
1 |
2 | main is b.Goober from app
3 |
4 | [app]
5 | load ${basedir}/src/test/test-data/a.jar
6 | load ${basedir}/src/test/test-data/b.jar
7 |
--------------------------------------------------------------------------------
/src/test/test-data/valid-enh-launch.conf:
--------------------------------------------------------------------------------
1 |
2 | main is b.B from app
3 |
4 | [app]
5 | load ${basedir}/src/test/test-data/a.jar
6 | load ${basedir}/src/test/test-data/b.jar
7 |
--------------------------------------------------------------------------------
/src/test/test-data/valid-enh-launch-exitCode.conf:
--------------------------------------------------------------------------------
1 |
2 | main is b.Bb from app
3 |
4 | [app]
5 | load ${basedir}/src/test/test-data/a.jar
6 | load ${basedir}/src/test/test-data/b.jar
7 |
--------------------------------------------------------------------------------
/src/test/test-data/launch-nomethod.conf:
--------------------------------------------------------------------------------
1 |
2 | main is c.C from app
3 |
4 | [app]
5 | load ${basedir}/src/test/test-data/a.jar
6 | load ${basedir}/src/test/test-data/b.jar
7 | load ${basedir}/src/test/test-data/c.jar
8 |
--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name: Release Drafter
2 | on:
3 | push:
4 | branches:
5 | - master
6 | jobs:
7 | update_release_draft:
8 | uses: codehaus-plexus/.github/.github/workflows/release-drafter.yml@master
9 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "maven"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 | - package-ecosystem: "github-actions"
8 | directory: "/"
9 | schedule:
10 | interval: "daily"
11 |
--------------------------------------------------------------------------------
/src/test/test-data/resources/classworlds.conf:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Define the main entry-point
3 | # ------------------------------------------------------------
4 |
5 | main is foo from root
6 |
7 | # ------------------------------------------------------------
8 | # Start defining realms
9 | # ------------------------------------------------------------
10 |
11 | [root]
12 | load ${basedir}/src/test/test-data/resources/werkflow.jar
13 |
--------------------------------------------------------------------------------
/src/test/test-data/optionally-nonexistent.conf:
--------------------------------------------------------------------------------
1 |
2 | # ------------------------------------------------------------
3 | # Define the main entry-point
4 | # ------------------------------------------------------------
5 |
6 | main is org.apache.maven.app.App from opt
7 |
8 | # ------------------------------------------------------------
9 | # Start defining realms
10 | # ------------------------------------------------------------
11 |
12 | [opt]
13 | optionally /non/existant/path/*.jar
14 |
--------------------------------------------------------------------------------
/src/test/test-data/optionally-existent.conf:
--------------------------------------------------------------------------------
1 |
2 | # ------------------------------------------------------------
3 | # Define the main entry-point
4 | # ------------------------------------------------------------
5 |
6 | main is org.apache.maven.app.App from opt
7 |
8 | # ------------------------------------------------------------
9 | # Start defining realms
10 | # ------------------------------------------------------------
11 |
12 | [opt]
13 | optionally ${basedir}/target/test-lib/jakarta.xml.bind-api-4.0.4.jar
14 |
15 |
--------------------------------------------------------------------------------
/src/test/test-data/inheritance.conf:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Define the main entry-point
3 | # ------------------------------------------------------------
4 |
5 | main is org.apache.maven.app.App from root.maven
6 |
7 | # ------------------------------------------------------------
8 | # Start defining realms
9 | # ------------------------------------------------------------
10 |
11 | [root]
12 | load ${basedir}/src/test/test-data/a.jar
13 |
14 | [root.maven]
15 | load ${basedir}/src/test/test-data/b.jar
16 |
17 | [root.maven.plugin]
18 | load ${basedir}/src/test/test-data/c.jar
19 |
--------------------------------------------------------------------------------
/src/test/test-data/set-using-missing.conf:
--------------------------------------------------------------------------------
1 |
2 | # ------------------------------------------------------------
3 | # Define the main entry-point
4 | # ------------------------------------------------------------
5 |
6 | main is org.apache.maven.app.App from opt
7 |
8 | # ------------------------------------------------------------
9 | # Set properties
10 | # ------------------------------------------------------------
11 | set set.using.missing default testSet_Using_Missing_Default
12 | set set.using.filtered.default default ${user.home}/m2
13 |
14 | # ------------------------------------------------------------
15 | # Start defining realms
16 | # ------------------------------------------------------------
17 |
18 | [opt]
19 |
20 |
--------------------------------------------------------------------------------
/src/test/test-data/a.properties:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | #
3 | # Copyright 2001-2006 The Codehaus Foundation.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 |
18 | a properties
19 |
--------------------------------------------------------------------------------
/src/test/test-data/nested.properties:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | #
3 | # Copyright 2001-2006 The Codehaus Foundation.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 |
18 | nested.properties
19 |
--------------------------------------------------------------------------------
/src/test/test-data/valid.conf:
--------------------------------------------------------------------------------
1 |
2 | # ------------------------------------------------------------
3 | # Define the main entry-point
4 | # ------------------------------------------------------------
5 |
6 | main is org.apache.maven.app.App from maven
7 |
8 | # ------------------------------------------------------------
9 | # Start defining realms
10 | # ------------------------------------------------------------
11 |
12 | [xml]
13 | load ${basedir}/target/test-lib/jakarta.xml.bind-api-4.0.4.jar
14 |
15 | [ant]
16 | import jakarta.xml.bind from xml
17 | load ${basedir}/target/test-lib/ant-1.10.14.jar
18 |
19 | [maven]
20 | import jakarta.xml.bind from xml
21 | load ${basedir}/target/test-lib/log4j-api-2.23.1.jar
22 |
23 | [glob]
24 | load ${basedir}/src/test/test-data/*.jar
25 |
--------------------------------------------------------------------------------
/src/test/test-data/valid-from-from-from.conf:
--------------------------------------------------------------------------------
1 |
2 | # ------------------------------------------------------------
3 | # Define the main entry-point
4 | # ------------------------------------------------------------
5 |
6 | main is com.from.from.from.Main from from
7 |
8 | # ------------------------------------------------------------
9 | # Start defining realms
10 | # ------------------------------------------------------------
11 |
12 | [from]
13 | load ${basedir}/src/test/test-data/from-from-0.0.1-from-load-import.jar
14 |
15 | [ant]
16 | import com.from.from.from from from
17 | load ${basedir}/target/test-lib/ant-1.10.14.jar
18 |
19 | [maven]
20 | import com.from.from.from from from
21 | load ${basedir}/target/test-lib/log4j-api-2.23.1.jar
22 |
23 | [glob]
24 | load ${basedir}/src/test/test-data/*.jar
25 |
--------------------------------------------------------------------------------
/src/test/test-data/set-using-existent.conf:
--------------------------------------------------------------------------------
1 |
2 | # ------------------------------------------------------------
3 | # Define the main entry-point
4 | # ------------------------------------------------------------
5 |
6 | main is org.apache.maven.app.App from opt
7 |
8 | # ------------------------------------------------------------
9 | # Set properties
10 | # ------------------------------------------------------------
11 | set set.using.existent using ${basedir}/src/test/test-data/set-using-existent.properties
12 | set set.using.default using ${basedir}/src/test/test-data/set-using-existent.properties default testSet_Using_Existent_Default
13 |
14 | # ------------------------------------------------------------
15 | # Start defining realms
16 | # ------------------------------------------------------------
17 |
18 | [opt]
19 |
20 |
--------------------------------------------------------------------------------
/src/test/test-data/set-using-existent.properties:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | #
3 | # Copyright 2001-2006 The Codehaus Foundation.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 |
18 | set.using.existent=testSet_Using_Existent
19 |
20 |
--------------------------------------------------------------------------------
/src/test/test-data/set-using-nonexistent.conf:
--------------------------------------------------------------------------------
1 |
2 | # ------------------------------------------------------------
3 | # Define the main entry-point
4 | # ------------------------------------------------------------
5 |
6 | main is org.apache.maven.app.App from opt
7 |
8 | # ------------------------------------------------------------
9 | # Set properties
10 | # ------------------------------------------------------------
11 | set set.using.nonexistent using ${basedir}/src/test/test-data/set-using-nonexistent.properties
12 | set set.using.nonexistent.default using ${basedir}/src/test/test-data/set-using-nonexistent.properties default testSet_Using_NonExistent_Default
13 |
14 | # ------------------------------------------------------------
15 | # Start defining realms
16 | # ------------------------------------------------------------
17 |
18 | [opt]
19 |
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Plexus-Classworlds
2 | ==================
3 |
4 | [](http://www.apache.org/licenses/)
5 | [](https://search.maven.org/artifact/org.codehaus.plexus/plexus-classworlds)
6 | [](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/content/org/codehaus/plexus/plexus-classworlds/README.md)
7 | 
8 |
9 | Current master is now at https://github.com/codehaus-plexus/plexus-classworlds
10 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/ClassWorldListener.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
20 |
21 | public interface ClassWorldListener {
22 | void realmCreated(ClassRealm realm);
23 |
24 | void realmDisposed(ClassRealm realm);
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/AbstractClassWorldsTestCase.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.net.URL;
20 |
21 | /**
22 | * @author Jason van Zyl
23 | */
24 | public abstract class AbstractClassWorldsTestCase {
25 | protected URL getJarUrl(String jarName) {
26 | return TestUtil.getTestResourceUrl(jarName);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | name: GitHub CI
19 |
20 | on: [push, pull_request]
21 |
22 | jobs:
23 | build:
24 | name: Build it
25 | uses: codehaus-plexus/.github/.github/workflows/maven.yml@master
26 |
27 | deploy:
28 | name: Deploy
29 | needs: build
30 | uses: codehaus-plexus/.github/.github/workflows/maven-deploy.yml@master
31 | secrets: inherit
32 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/UrlUtilsTest.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import org.junit.jupiter.api.Test;
20 |
21 | import static org.junit.jupiter.api.Assertions.assertEquals;
22 |
23 | class UrlUtilsTest {
24 |
25 | @Test
26 | void normalizeUrlPath() {
27 | assertEquals("org/codehaus/Test.class", UrlUtils.normalizeUrlPath("org/codehaus/Test.class"));
28 | assertEquals("org/Test.class", UrlUtils.normalizeUrlPath("org/codehaus/../Test.class"));
29 | assertEquals("../../some.jar/org/Test.class", UrlUtils.normalizeUrlPath("../../some.jar/org/Test.class"));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/strategy/StrategyFactory.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.strategy;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
20 |
21 | /**
22 | * StrategyFactory loads a strategy, either default or from a given hint.
23 | */
24 | public class StrategyFactory {
25 |
26 | public static Strategy getStrategy(ClassRealm realm) {
27 | return getStrategy(realm, "default");
28 | }
29 |
30 | public static Strategy getStrategy(ClassRealm realm, String hint) {
31 | // TODO: Here we shall check hint to load non-default strategies
32 |
33 | return new SelfFirstStrategy(realm);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/strategy/Strategy.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.strategy;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.IOException;
20 | import java.net.URL;
21 | import java.util.Enumeration;
22 |
23 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
24 |
25 | /**
26 | * A strategy is a class for defining how classes and resources are located
27 | * in classworlds.
28 | */
29 | public interface Strategy {
30 |
31 | Class> loadClass(String name) throws ClassNotFoundException;
32 |
33 | URL getResource(String name);
34 |
35 | @SuppressWarnings("RedundantThrows")
36 | Enumeration getResources(String name) throws IOException;
37 |
38 | ClassRealm getRealm();
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/BytesURLConnection.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.ByteArrayInputStream;
20 | import java.io.InputStream;
21 | import java.net.URL;
22 | import java.net.URLConnection;
23 |
24 | /**
25 | */
26 | @Deprecated
27 | public class BytesURLConnection extends URLConnection {
28 | protected final byte[] content;
29 |
30 | protected int offset;
31 |
32 | protected int length;
33 |
34 | public BytesURLConnection(URL url, byte[] content) {
35 | super(url);
36 | this.content = content;
37 | }
38 |
39 | public void connect() {}
40 |
41 | public InputStream getInputStream() {
42 | return new ByteArrayInputStream(content);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/BytesURLStreamHandler.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.net.URL;
20 | import java.net.URLConnection;
21 | import java.net.URLStreamHandler;
22 |
23 | /**
24 | * @author Hani Suleiman (hani@formicary.net)
25 | * Date: Oct 20, 2003
26 | * Time: 12:45:18 AM
27 | */
28 | @Deprecated
29 | public class BytesURLStreamHandler extends URLStreamHandler {
30 | final byte[] content;
31 |
32 | int offset;
33 |
34 | int length;
35 |
36 | public BytesURLStreamHandler(byte[] content) {
37 | this.content = content;
38 | }
39 |
40 | public URLConnection openConnection(URL url) {
41 | return new BytesURLConnection(url, content);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/launcher/ConfigurationException.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.launcher;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /**
20 | * Indicates an error during Launcher configuration.
21 | *
22 | * @author bob mcwhirter
23 | */
24 | public class ConfigurationException extends Exception {
25 | /**
26 | * Construct.
27 | *
28 | * @param msg The message.
29 | */
30 | public ConfigurationException(String msg) {
31 | super(msg);
32 | }
33 |
34 | /**
35 | * Construct.
36 | *
37 | * @param msg The message.
38 | * @param lineNo The number of configuraton line where the problem occured.
39 | * @param line The configuration line where the problem occured.
40 | */
41 | public ConfigurationException(String msg, int lineNo, String line) {
42 | super(msg + " (" + lineNo + "): " + line);
43 | }
44 |
45 | protected ConfigurationException(Exception cause) {
46 | super(cause);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/TestUtil.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.File;
20 | import java.net.MalformedURLException;
21 | import java.net.URL;
22 |
23 | /**
24 | * @author Ben Walding
25 | */
26 | public class TestUtil {
27 |
28 | public static URL getTestResourceUrl(String resourceName) {
29 | File baseDir = new File(getBasedir());
30 |
31 | File testDir = new File(baseDir, "src/test/test-data");
32 |
33 | File resourceFile = new File(testDir, resourceName);
34 |
35 | try {
36 | return resourceFile.toURI().toURL();
37 | } catch (MalformedURLException e) {
38 | throw new RuntimeException(e);
39 | }
40 | }
41 |
42 | public static String getBasedir() {
43 | String basedir = System.getProperty("basedir");
44 |
45 | /* do our best if we are not running from surefire */
46 | if (basedir == null || basedir.isEmpty()) {
47 | basedir = (new File("")).getAbsolutePath();
48 | }
49 |
50 | return basedir;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/site/site.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/UrlUtils.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.net.URL;
20 | import java.net.URLClassLoader;
21 | import java.util.Arrays;
22 | import java.util.HashSet;
23 | import java.util.Set;
24 |
25 | /**
26 | * @author Jason van Zyl
27 | */
28 | public class UrlUtils {
29 | public static String normalizeUrlPath(String name) {
30 | if (name.startsWith("/")) {
31 | name = name.substring(1);
32 | }
33 |
34 | // Looking for org/codehaus/werkflow/personality/basic/../common/core-idioms.xml
35 | // | i |
36 | // +-------+ remove
37 | //
38 | int i = name.indexOf("/..");
39 |
40 | // Can't be at the beginning because we have no root to refer to so
41 | // we start at 1.
42 | if (i > 0) {
43 | int j = name.lastIndexOf("/", i - 1);
44 |
45 | if (j >= 0) {
46 | name = name.substring(0, j) + name.substring(i + 3);
47 | }
48 | }
49 |
50 | return name;
51 | }
52 |
53 | public static Set getURLs(URLClassLoader loader) {
54 | return new HashSet<>(Arrays.asList(loader.getURLs()));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/Launcher.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /**
20 | * A compatibility wrapper for org.codehaus.plexus.classworlds.launcher.Launcher
21 | * provided for legacy code
22 | *
23 | * @author Andrew Williams
24 | */
25 | @Deprecated
26 | public class Launcher extends org.codehaus.plexus.classworlds.launcher.Launcher {
27 | public Launcher() {}
28 |
29 | // ------------------------------------------------------------
30 | // Class methods
31 | // ------------------------------------------------------------
32 |
33 | /**
34 | * Launch the launcher from the command line.
35 | * Will exit using System.exit with an exit code of 0 for success, 100 if there was an unknown exception,
36 | * or some other code for an application error.
37 | *
38 | * @param args The application command-line arguments.
39 | */
40 | public static void main(String[] args) {
41 | org.codehaus.plexus.classworlds.launcher.Launcher.main(args);
42 | }
43 |
44 | /**
45 | * Launch the launcher.
46 | *
47 | * @param args The application command-line arguments.
48 | * @return an integer exit code
49 | * @throws Exception If an error occurs.
50 | */
51 | public static int mainWithExitCode(String[] args) throws Exception {
52 | return org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(args);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/LICENSE-Codehaus.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | $Id$
5 |
6 | Copyright 2002 (C) The Codehaus. All Rights Reserved.
7 |
8 | Redistribution and use of this software and associated documentation
9 | ("Software"), with or without modification, are permitted provided
10 | that the following conditions are met:
11 |
12 | 1. Redistributions of source code must retain copyright
13 | statements and notices. Redistributions must also contain a
14 | copy of this document.
15 |
16 | 2. Redistributions in binary form must reproduce the
17 | above copyright notice, this list of conditions and the
18 | following disclaimer in the documentation and/or other
19 | materials provided with the distribution.
20 |
21 | 3. The name "classworlds" must not be used to endorse or promote
22 | products derived from this Software without prior written
23 | permission of The Codehaus. For written permission, please
24 | contact bob@codehaus.org.
25 |
26 | 4. Products derived from this Software may not be called "classworlds"
27 | nor may "classworlds" appear in their names without prior written
28 | permission of The Codehaus. "classworlds" is a registered
29 | trademark of The Codehaus.
30 |
31 | 5. Due credit should be given to The Codehaus.
32 | (http://classworlds.codehaus.org/).
33 |
34 | THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
35 | ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
36 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
37 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
38 | THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
39 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
43 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
45 | OF THE POSSIBILITY OF SUCH DAMAGE.
46 |
47 | */
48 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/strategy/AbstractStrategy.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.strategy;
2 |
3 | import java.net.URL;
4 | import java.util.Collection;
5 | import java.util.Collections;
6 | import java.util.Enumeration;
7 | import java.util.LinkedHashSet;
8 |
9 | import org.codehaus.plexus.classworlds.UrlUtils;
10 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
11 |
12 | /*
13 | * Copyright 2001-2006 Codehaus Foundation.
14 | *
15 | * Licensed under the Apache License, Version 2.0 (the "License");
16 | * you may not use this file except in compliance with the License.
17 | * You may obtain a copy of the License at
18 | *
19 | * http://www.apache.org/licenses/LICENSE-2.0
20 | *
21 | * Unless required by applicable law or agreed to in writing, software
22 | * distributed under the License is distributed on an "AS IS" BASIS,
23 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 | * See the License for the specific language governing permissions and
25 | * limitations under the License.
26 | */
27 |
28 | /**
29 | * @author Jason van Zyl
30 | */
31 | public abstract class AbstractStrategy implements Strategy {
32 |
33 | protected final ClassRealm realm;
34 |
35 | public AbstractStrategy(ClassRealm realm) {
36 | this.realm = realm;
37 | }
38 |
39 | protected String getNormalizedResource(String name) {
40 | return UrlUtils.normalizeUrlPath(name);
41 | }
42 |
43 | protected Enumeration combineResources(Enumeration en1, Enumeration en2, Enumeration en3) {
44 | Collection urls = new LinkedHashSet<>();
45 |
46 | addAll(urls, en1);
47 | addAll(urls, en2);
48 | addAll(urls, en3);
49 |
50 | return Collections.enumeration(urls);
51 | }
52 |
53 | private void addAll(Collection target, Enumeration en) {
54 | if (en != null) {
55 | while (en.hasMoreElements()) {
56 | target.add(en.nextElement());
57 | }
58 | }
59 | }
60 |
61 | public ClassRealm getRealm() {
62 | return realm;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ClassWorld.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.util.Collection;
20 |
21 | /**
22 | * A compatibility wrapper for org.codehaus.plexus.classworlds.ClassWorld
23 | * provided for legacy code
24 | *
25 | * @author Andrew Williams
26 | */
27 | @SuppressWarnings("rawtypes")
28 | @Deprecated
29 | public class ClassWorld {
30 | private ClassWorldAdapter adapter;
31 |
32 | public ClassWorld(String realmId, ClassLoader classLoader) {
33 | adapter = ClassWorldAdapter.getInstance(new org.codehaus.plexus.classworlds.ClassWorld(realmId, classLoader));
34 | }
35 |
36 | public ClassWorld() {
37 | adapter = ClassWorldAdapter.getInstance(new org.codehaus.plexus.classworlds.ClassWorld());
38 | }
39 |
40 | public ClassWorld(boolean ignore) {
41 | /* fake */
42 | }
43 |
44 | public ClassRealm newRealm(String id) throws DuplicateRealmException {
45 | return adapter.newRealm(id);
46 | }
47 |
48 | public ClassRealm newRealm(String id, ClassLoader classLoader) throws DuplicateRealmException {
49 | return adapter.newRealm(id, classLoader);
50 | }
51 |
52 | public void disposeRealm(String id) throws NoSuchRealmException {
53 | adapter.disposeRealm(id);
54 | }
55 |
56 | public ClassRealm getRealm(String id) throws NoSuchRealmException {
57 | return adapter.getRealm(id);
58 | }
59 |
60 | public Collection getRealms() {
61 | return adapter.getRealms();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/realm/NoSuchRealmException.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.realm;
2 |
3 | import org.codehaus.plexus.classworlds.ClassWorld;
4 | import org.codehaus.plexus.classworlds.ClassWorldException;
5 |
6 | /*
7 | * Copyright 2001-2006 Codehaus Foundation.
8 | *
9 | * Licensed under the Apache License, Version 2.0 (the "License");
10 | * you may not use this file except in compliance with the License.
11 | * You may obtain a copy of the License at
12 | *
13 | * http://www.apache.org/licenses/LICENSE-2.0
14 | *
15 | * Unless required by applicable law or agreed to in writing, software
16 | * distributed under the License is distributed on an "AS IS" BASIS,
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | * See the License for the specific language governing permissions and
19 | * limitations under the License.
20 | */
21 |
22 | /**
23 | * Indicates an attempt to retrieve a ClassRealm from a
24 | * ClassWorld with an invalid id.
25 | *
26 | * @author bob mcwhirter
27 | */
28 | public class NoSuchRealmException extends ClassWorldException {
29 | // ------------------------------------------------------------
30 | // Instance members
31 | // ------------------------------------------------------------
32 |
33 | /**
34 | * The realm id.
35 | */
36 | private final String id;
37 |
38 | // ------------------------------------------------------------
39 | // Constructors
40 | // ------------------------------------------------------------
41 |
42 | /**
43 | * Construct.
44 | *
45 | * @param world The world.
46 | * @param id The realm id.
47 | */
48 | public NoSuchRealmException(ClassWorld world, String id) {
49 | super(world, id);
50 | this.id = id;
51 | }
52 |
53 | // ------------------------------------------------------------
54 | // Instance methods
55 | // ------------------------------------------------------------
56 |
57 | /**
58 | * Retrieve the invalid realm id.
59 | *
60 | * @return The id.
61 | */
62 | public String getId() {
63 | return this.id;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/realm/DuplicateRealmException.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.realm;
2 |
3 | import org.codehaus.plexus.classworlds.ClassWorld;
4 | import org.codehaus.plexus.classworlds.ClassWorldException;
5 |
6 | /*
7 | * Copyright 2001-2006 Codehaus Foundation.
8 | *
9 | * Licensed under the Apache License, Version 2.0 (the "License");
10 | * you may not use this file except in compliance with the License.
11 | * You may obtain a copy of the License at
12 | *
13 | * http://www.apache.org/licenses/LICENSE-2.0
14 | *
15 | * Unless required by applicable law or agreed to in writing, software
16 | * distributed under the License is distributed on an "AS IS" BASIS,
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | * See the License for the specific language governing permissions and
19 | * limitations under the License.
20 | */
21 |
22 | /**
23 | * Indicates an attempt to add a ClassRealm to a
24 | * ClassWorld with a duplicate id.
25 | *
26 | * @author bob mcwhirter
27 | */
28 | public class DuplicateRealmException extends ClassWorldException {
29 | // ------------------------------------------------------------
30 | // Instance members
31 | // ------------------------------------------------------------
32 |
33 | /**
34 | * The realm id.
35 | */
36 | private final String id;
37 |
38 | // ------------------------------------------------------------
39 | // Constructors
40 | // ------------------------------------------------------------
41 |
42 | /**
43 | * Construct.
44 | *
45 | * @param world The world.
46 | * @param id The realm id.
47 | */
48 | public DuplicateRealmException(ClassWorld world, String id) {
49 | super(world, id);
50 | this.id = id;
51 | }
52 |
53 | // ------------------------------------------------------------
54 | // Instance methods
55 | // ------------------------------------------------------------
56 |
57 | /**
58 | * Retrieve the duplicate realm id.
59 | *
60 | * @return The id.
61 | */
62 | public String getId() {
63 | return this.id;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/ClassWorldException.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /**
20 | * Base exception for ClassWorld errors.
21 | *
22 | * @author bob mcwhirter
23 | */
24 | public class ClassWorldException extends Exception {
25 | // ------------------------------------------------------------
26 | // Instance members
27 | // ------------------------------------------------------------
28 |
29 | /**
30 | * The world.
31 | */
32 | private final ClassWorld world;
33 |
34 | // ------------------------------------------------------------
35 | // Constructors
36 | // ------------------------------------------------------------
37 |
38 | /**
39 | * Construct.
40 | *
41 | * @param world The world.
42 | */
43 | public ClassWorldException(final ClassWorld world) {
44 | this.world = world;
45 | }
46 |
47 | /**
48 | * Construct.
49 | *
50 | * @param world The world.
51 | * @param msg The detail message.
52 | */
53 | public ClassWorldException(final ClassWorld world, final String msg) {
54 | super(msg);
55 | this.world = world;
56 | }
57 |
58 | // ------------------------------------------------------------
59 | // Instance methods
60 | // ------------------------------------------------------------
61 |
62 | /**
63 | * Retrieve the world.
64 | *
65 | * @return The world.
66 | */
67 | public ClassWorld getWorld() {
68 | return this.world;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/launcher/ConfigurationHandler.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.launcher;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.File;
20 | import java.net.URL;
21 |
22 | import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
23 | import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
24 |
25 | /**
26 | * Receive notification of the logical content of launcher configuration, independently from parsing.
27 | *
28 | * @author Igor Fedorenko
29 | */
30 | public interface ConfigurationHandler {
31 |
32 | /**
33 | * Define the main class name
34 | * @param mainClassName the main class name
35 | * @param mainRealmName the main realm from which the main class is loaded
36 | */
37 | void setAppMain(String mainClassName, String mainRealmName);
38 |
39 | /**
40 | * Define a new realm
41 | * @param realmName the new realm name
42 | * @throws DuplicateRealmException when realm with name already exists
43 | */
44 | void addRealm(String realmName) throws DuplicateRealmException;
45 |
46 | /**
47 | * Add an import specification from a realm
48 | * @param realmName the realm name
49 | * @param importSpec the import specification
50 | * @throws NoSuchRealmException if realm doesn't exist
51 | */
52 | void addImportFrom(String realmName, String importSpec) throws NoSuchRealmException;
53 |
54 | /**
55 | * Add a file to the realm
56 | * @param file the file to load content from
57 | */
58 | void addLoadFile(File file);
59 |
60 | /**
61 | * Add an URL to the realm
62 | * @param url the url to load content from
63 | */
64 | void addLoadURL(URL url);
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/strategy/SelfFirstStrategy.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.strategy;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7 | * in compliance with the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software distributed under the License
12 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 | * or implied. See the License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | import java.io.IOException;
18 | import java.net.URL;
19 | import java.util.Enumeration;
20 |
21 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
22 |
23 | /**
24 | * @author Jason van Zyl
25 | */
26 | public class SelfFirstStrategy extends AbstractStrategy {
27 |
28 | public SelfFirstStrategy(ClassRealm realm) {
29 | super(realm);
30 | }
31 |
32 | public Class> loadClass(String name) throws ClassNotFoundException {
33 | Class> clazz = realm.loadClassFromImport(name);
34 |
35 | if (clazz == null) {
36 | clazz = realm.loadClassFromSelf(name);
37 |
38 | if (clazz == null) {
39 | clazz = realm.loadClassFromParent(name);
40 |
41 | if (clazz == null) {
42 | throw new ClassNotFoundException(name);
43 | }
44 | }
45 | }
46 |
47 | return clazz;
48 | }
49 |
50 | public URL getResource(String name) {
51 | URL resource = realm.loadResourceFromImport(name);
52 |
53 | if (resource == null) {
54 | resource = realm.loadResourceFromSelf(name);
55 |
56 | if (resource == null) {
57 | resource = realm.loadResourceFromParent(name);
58 | }
59 | }
60 |
61 | return resource;
62 | }
63 |
64 | @SuppressWarnings("RedundantThrows")
65 | public Enumeration getResources(String name) throws IOException {
66 | Enumeration imports = realm.loadResourcesFromImport(name);
67 | Enumeration self = realm.loadResourcesFromSelf(name);
68 | Enumeration parent = realm.loadResourcesFromParent(name);
69 |
70 | return combineResources(imports, self, parent);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/strategy/ParentFirstStrategy.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.strategy;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7 | * in compliance with the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software distributed under the License
12 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 | * or implied. See the License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | import java.io.IOException;
18 | import java.net.URL;
19 | import java.util.Enumeration;
20 |
21 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
22 |
23 | /**
24 | * @author Jason van Zyl
25 | */
26 | public class ParentFirstStrategy extends AbstractStrategy {
27 |
28 | public ParentFirstStrategy(ClassRealm realm) {
29 | super(realm);
30 | }
31 |
32 | public Class> loadClass(String name) throws ClassNotFoundException {
33 | Class> clazz = realm.loadClassFromImport(name);
34 |
35 | if (clazz == null) {
36 | clazz = realm.loadClassFromParent(name);
37 |
38 | if (clazz == null) {
39 | clazz = realm.loadClassFromSelf(name);
40 |
41 | if (clazz == null) {
42 | throw new ClassNotFoundException(name);
43 | }
44 | }
45 | }
46 |
47 | return clazz;
48 | }
49 |
50 | public URL getResource(String name) {
51 | URL resource = realm.loadResourceFromImport(name);
52 |
53 | if (resource == null) {
54 | resource = realm.loadResourceFromParent(name);
55 |
56 | if (resource == null) {
57 | resource = realm.loadResourceFromSelf(name);
58 | }
59 | }
60 |
61 | return resource;
62 | }
63 |
64 | @SuppressWarnings("RedundantThrows")
65 | public Enumeration getResources(String name) throws IOException {
66 | Enumeration imports = realm.loadResourcesFromImport(name);
67 | Enumeration parent = realm.loadResourcesFromParent(name);
68 | Enumeration self = realm.loadResourcesFromSelf(name);
69 |
70 | return combineResources(imports, parent, self);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ConfiguratorAdapter.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.net.MalformedURLException;
22 |
23 | /**
24 | */
25 | @Deprecated
26 | public class ConfiguratorAdapter extends Configurator {
27 |
28 | public static ConfiguratorAdapter getInstance(
29 | org.codehaus.plexus.classworlds.launcher.Configurator newConfig, Launcher launcher) {
30 | return new ConfiguratorAdapter(newConfig, launcher);
31 | }
32 |
33 | public static ConfiguratorAdapter getInstance(
34 | org.codehaus.plexus.classworlds.launcher.Configurator newConfig, ClassWorld world) {
35 | return new ConfiguratorAdapter(newConfig, world);
36 | }
37 |
38 | private final org.codehaus.plexus.classworlds.launcher.Configurator config;
39 |
40 | private ConfiguratorAdapter(org.codehaus.plexus.classworlds.launcher.Configurator config, Launcher launcher) {
41 | super(launcher);
42 | this.config = config;
43 | }
44 |
45 | private ConfiguratorAdapter(org.codehaus.plexus.classworlds.launcher.Configurator config, ClassWorld world) {
46 | super(world);
47 | this.config = config;
48 | }
49 |
50 | public void associateRealms() {
51 | config.associateRealms();
52 | }
53 |
54 | @SuppressWarnings("DuplicateThrows")
55 | public void configureAdapter(InputStream is)
56 | throws IOException, MalformedURLException, ConfigurationException, DuplicateRealmException,
57 | NoSuchRealmException {
58 | try {
59 | config.configure(is);
60 | } catch (org.codehaus.plexus.classworlds.launcher.ConfigurationException e) {
61 | throw new ConfigurationException(e.getMessage());
62 | } catch (org.codehaus.plexus.classworlds.realm.DuplicateRealmException e) {
63 | throw new DuplicateRealmException(ClassWorldAdapter.getInstance(e.getWorld()), e.getId());
64 | } catch (org.codehaus.plexus.classworlds.realm.NoSuchRealmException e) {
65 | throw new NoSuchRealmException(ClassWorldAdapter.getInstance(e.getWorld()), e.getId());
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/strategy/OsgiBundleStrategy.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.strategy;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.IOException;
20 | import java.net.URL;
21 | import java.util.Enumeration;
22 |
23 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
24 |
25 | public class OsgiBundleStrategy extends AbstractStrategy {
26 |
27 | // java.* from parent
28 | // imported packages [Import-Package header with explicit constraints on the exporter]
29 | // requires bundle [Required-Bundle]
30 | // self [Bundle-Classpath header]
31 | // attached fragments
32 | //
33 | // We need to trya and be OSGi r4 compliant in the loading of all the bundles so that we can try to
34 | // load eclipse without requiring equinox. Or any other OSGi container for that matter.
35 | public OsgiBundleStrategy(ClassRealm realm) {
36 | super(realm);
37 | }
38 |
39 | public Class> loadClass(String name) throws ClassNotFoundException {
40 | Class> clazz = realm.loadClassFromImport(name);
41 |
42 | if (clazz == null) {
43 | clazz = realm.loadClassFromSelf(name);
44 |
45 | if (clazz == null) {
46 | clazz = realm.loadClassFromParent(name);
47 |
48 | if (clazz == null) {
49 | throw new ClassNotFoundException(name);
50 | }
51 | }
52 | }
53 |
54 | return clazz;
55 | }
56 |
57 | public URL getResource(String name) {
58 | URL resource = realm.loadResourceFromImport(name);
59 |
60 | if (resource == null) {
61 | resource = realm.loadResourceFromSelf(name);
62 |
63 | if (resource == null) {
64 | resource = realm.loadResourceFromParent(name);
65 | }
66 | }
67 |
68 | return resource;
69 | }
70 |
71 | @SuppressWarnings("RedundantThrows")
72 | public Enumeration getResources(String name) throws IOException {
73 | Enumeration imports = realm.loadResourcesFromImport(name);
74 | Enumeration self = realm.loadResourcesFromSelf(name);
75 | Enumeration parent = realm.loadResourcesFromParent(name);
76 |
77 | return combineResources(imports, self, parent);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/site/xdoc/index.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Plexus Classworlds
7 | bob mcwhirter
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Plexus Classworlds is a framework for container developers
16 | who require complex manipulation of Java's ClassLoaders. Java's
17 | native ClassLoader mechanisms and classes can cause
18 | much headache and confusion for certain types of application
19 | developers. Projects which involve dynamic loading of components
20 | or otherwise represent a 'container' can benefit from the classloading
21 | control provided by Classworlds.
22 |
23 |
24 |
25 | Plexus Classworlds provides a richer set of semantics for
26 | class loading than Java's normal mechanisms, while still being
27 | able to provide a ClassLoader interface to integrate
28 | seamlessly with the Java environment.
29 |
30 |
31 |
32 | The Classworlds model does away with the hierarchy
33 | normally associated with ClassLoaders. Instead,
34 | ClassWorld provides a
35 | pool of ClassRealms
36 | which can import arbitrary packages from other ClassRealms.
37 | Effectively, Classworlds turns the old-style
38 | hierarchy into a directed graph.
39 |
40 |
41 |
42 | In a application container environment, the container may
43 | have a realm capable of loading on the container/component
44 | contract interfaces and classes. Another realm is created
45 | for each component which imports the contract classes from
46 | the container realm.
47 |
48 |
49 |
50 | This model allows for fine-grained control of which
51 | classloader loads any particular class. This form of
52 | partial isolation can reduce the myriad strange errors
53 | that are produced by loading classes from multiple
54 | loaders.
55 |
56 |
57 |
58 | In addition, Plexus Classworlds provides a
59 | launcher
60 | to assist in the creation of classloaders and ClassRealms
61 | from a configuration file and the launching of the application's main
62 | method from the correct class loaded through the correct classloader.
63 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ConfigurationException.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 |
5 | Copyright 2002 (C) The Werken Company. All Rights Reserved.
6 |
7 | Redistribution and use of this software and associated documentation
8 | ("Software"), with or without modification, are permitted provided
9 | that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain copyright
12 | statements and notices. Redistributions must also contain a
13 | copy of this document.
14 |
15 | 2. Redistributions in binary form must reproduce the
16 | above copyright notice, this list of conditions and the
17 | following disclaimer in the documentation and/or other
18 | materials provided with the distribution.
19 |
20 | 3. The name "classworlds" must not be used to endorse or promote
21 | products derived from this Software without prior written
22 | permission of The Werken Company. For written permission,
23 | please contact bob@werken.com.
24 |
25 | 4. Products derived from this Software may not be called "classworlds"
26 | nor may "classworlds" appear in their names without prior written
27 | permission of The Werken Company. "classworlds" is a registered
28 | trademark of The Werken Company.
29 |
30 | 5. Due credit should be given to The Werken Company.
31 | (http://classworlds.werken.com/).
32 |
33 | THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
34 | ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
35 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
37 | THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
42 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
44 | OF THE POSSIBILITY OF SUCH DAMAGE.
45 |
46 | */
47 |
48 | /**
49 | * Indicates an error during Launcher configuration.
50 | *
51 | * @author bob mcwhirter
52 | */
53 | @Deprecated
54 | public class ConfigurationException extends Exception {
55 | /**
56 | * Construct.
57 | *
58 | * @param msg The message.
59 | */
60 | public ConfigurationException(String msg) {
61 | super(msg);
62 | }
63 |
64 | /**
65 | * Construct.
66 | *
67 | * @param msg The message.
68 | * @param lineNo The number of configuraton line where the problem occured.
69 | * @param line The configuration line where the problem occured.
70 | */
71 | public ConfigurationException(String msg, int lineNo, String line) {
72 | super(msg + " (" + lineNo + "): " + line);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/realm/FilteredClassRealm.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.codehaus.plexus.classworlds.realm;
20 |
21 | import java.io.IOException;
22 | import java.net.URL;
23 | import java.util.Collections;
24 | import java.util.Enumeration;
25 | import java.util.function.Predicate;
26 |
27 | import org.codehaus.plexus.classworlds.ClassWorld;
28 |
29 | /**
30 | * Similar to {@link ClassRealm} but only exposing some resources of the underlying URL.
31 | * Only supposed to be called from {@link ClassWorld}.
32 | */
33 | public class FilteredClassRealm extends ClassRealm {
34 | private final Predicate filter;
35 |
36 | /**
37 | * Creates a new class realm.
38 | *
39 | * @param filter a predicate to apply to each resource name to determine if it should be loaded through this class loader
40 | * @param world The class world this realm belongs to, must not be null.
41 | * @param id The identifier for this realm, must not be null.
42 | * @param baseClassLoader The base class loader for this realm, may be null to use the bootstrap class
43 | * loader.
44 | */
45 | public FilteredClassRealm(Predicate filter, ClassWorld world, String id, ClassLoader baseClassLoader) {
46 | super(world, id, baseClassLoader);
47 | this.filter = filter;
48 | }
49 |
50 | @Override
51 | protected Class> findClassInternal(String name) throws ClassNotFoundException {
52 | String resourceName = name.replace('.', '/').concat(".class");
53 | if (!filter.test(resourceName)) {
54 | throw new ClassNotFoundException(name);
55 | }
56 | return super.findClassInternal(name);
57 | }
58 |
59 | @Override
60 | public URL findResource(String name) {
61 | if (!filter.test(name)) {
62 | return null;
63 | }
64 | return super.findResource(name);
65 | }
66 |
67 | @Override
68 | public Enumeration findResources(String name) throws IOException {
69 | if (!filter.test(name)) {
70 | return Collections.emptyEnumeration();
71 | }
72 | return super.findResources(name);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/launcher/ConfigurationParserTest.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.launcher;
2 |
3 | import org.codehaus.plexus.classworlds.AbstractClassWorldsTestCase;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static org.junit.jupiter.api.Assertions.assertEquals;
7 | import static org.junit.jupiter.api.Assertions.assertTrue;
8 | import static org.junit.jupiter.api.Assertions.fail;
9 |
10 | class ConfigurationParserTest extends AbstractClassWorldsTestCase {
11 |
12 | final ConfigurationParser configurator = new ConfigurationParser(null, System.getProperties());
13 |
14 | @Test
15 | void filterUnterminated() {
16 | try {
17 | this.configurator.filter("${cheese");
18 | fail("throw ConfigurationException");
19 | } catch (ConfigurationException e) {
20 | // expected and correct
21 | assertTrue(e.getMessage().startsWith("Unterminated"));
22 | }
23 | }
24 |
25 | @Test
26 | void filterSolitary() throws Exception {
27 | System.setProperty("classworlds.test.prop", "test prop value");
28 |
29 | String result = this.configurator.filter("${classworlds.test.prop}");
30 |
31 | assertEquals("test prop value", result);
32 | }
33 |
34 | @Test
35 | void filterAtStart() throws Exception {
36 | System.setProperty("classworlds.test.prop", "test prop value");
37 |
38 | String result = this.configurator.filter("${classworlds.test.prop}cheese");
39 |
40 | assertEquals("test prop valuecheese", result);
41 | }
42 |
43 | @Test
44 | void filterAtEnd() throws Exception {
45 | System.setProperty("classworlds.test.prop", "test prop value");
46 |
47 | String result = this.configurator.filter("cheese${classworlds.test.prop}");
48 |
49 | assertEquals("cheesetest prop value", result);
50 | }
51 |
52 | @Test
53 | void filterMultiple() throws Exception {
54 | System.setProperty("classworlds.test.prop.one", "test prop value one");
55 |
56 | System.setProperty("classworlds.test.prop.two", "test prop value two");
57 |
58 | String result =
59 | this.configurator.filter("I like ${classworlds.test.prop.one} and ${classworlds.test.prop.two} a lot");
60 |
61 | assertEquals("I like test prop value one and test prop value two a lot", result);
62 | }
63 |
64 | @Test
65 | void filterNonExistent() {
66 | try {
67 | this.configurator.filter("${gollygeewillikers}");
68 | fail("throw ConfigurationException");
69 | } catch (ConfigurationException e) {
70 | // expected and correct
71 | assertTrue(e.getMessage().startsWith("No such property"));
72 | }
73 | }
74 |
75 | @Test
76 | void filterInMiddle() throws Exception {
77 | System.setProperty("classworlds.test.prop", "test prop value");
78 |
79 | String result = this.configurator.filter("cheese${classworlds.test.prop}toast");
80 |
81 | assertEquals("cheesetest prop valuetoast", result);
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/site/xdoc/apiusage.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Classworlds API Usage
7 | bob mcwhirter
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | The Java API can be used to create new realms and connect
16 | realms together through importation of specific packages.
17 |
18 |
19 |
20 | The core of the Classworlds infrastructure is
21 | the
22 | ClassWorld
23 | class. An application must create a ClassWorld instance.
24 | It is advisable to store the instance as a singleton or some other
25 | handy location.
26 |
27 |
28 |
31 |
32 |
33 | Once a ClassWorld is created, realms within it
34 | can be created. These realms effectively only allow loading
35 | of the core JVM classes initially.
36 |
37 |
38 |
43 |
44 |
45 | In order to make each ClassRealm useful, constituents
46 | in form of URLs must be added to it where each can provide certain classes.
47 | The URL must return either a JAR or a directory on the default file system.
48 |
49 |
50 |
54 |
55 |
56 | ClassRealms can optionally be filtered to further restrict which classes/resources
57 | are exposed. The filter is provided as additional argument to world.newRealm( "filteredcontainer", myPredicate );
58 |
59 |
60 |
61 | Now, links between the various realms need to be created to allow
62 | classes loaded from one to be available to classes loaded in another.
63 |
64 |
65 |
69 |
70 |
71 | The container implementation can then be loaded from its realm
72 | and used.
73 |
74 |
75 |
81 |
82 |
83 | Ideally, the container itself would be responsible for creating
84 | a ClassRealm for each component that's loaded, and
85 | importing the component contract interfaces into the component's
86 | ClassRealm and using loadClass(..)
87 | to gain entry into the sandboxed component realm.
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ClassWorldAdapter.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.util.Collection;
20 | import java.util.Vector;
21 |
22 | /**
23 | * An adapter for ClassWorlds
24 | *
25 | * @author Andrew Williams
26 | */
27 | @SuppressWarnings("rawtypes")
28 | @Deprecated
29 | public class ClassWorldAdapter extends ClassWorld {
30 |
31 | public static ClassWorldAdapter getInstance(org.codehaus.plexus.classworlds.ClassWorld newWorld) {
32 | return new ClassWorldAdapter(newWorld);
33 | }
34 |
35 | private final org.codehaus.plexus.classworlds.ClassWorld world;
36 |
37 | private ClassWorldAdapter(org.codehaus.plexus.classworlds.ClassWorld newWorld) {
38 | super(false);
39 | this.world = newWorld;
40 | }
41 |
42 | public ClassRealm newRealm(String id) throws DuplicateRealmException {
43 | try {
44 | return ClassRealmAdapter.getInstance(world.newRealm(id));
45 | } catch (org.codehaus.plexus.classworlds.realm.DuplicateRealmException e) {
46 | throw new DuplicateRealmException(this, e.getId());
47 | }
48 | }
49 |
50 | public ClassRealm newRealm(String id, ClassLoader classLoader) throws DuplicateRealmException {
51 | try {
52 | return ClassRealmAdapter.getInstance(world.newRealm(id, classLoader));
53 | } catch (org.codehaus.plexus.classworlds.realm.DuplicateRealmException e) {
54 | throw new DuplicateRealmException(this, e.getId());
55 | }
56 | }
57 |
58 | public void disposeRealm(String id) throws NoSuchRealmException {
59 | try {
60 | world.disposeRealm(id);
61 | } catch (org.codehaus.plexus.classworlds.realm.NoSuchRealmException e) {
62 | throw new NoSuchRealmException(this, e.getId());
63 | }
64 | }
65 |
66 | public ClassRealm getRealm(String id) throws NoSuchRealmException {
67 | try {
68 | return ClassRealmAdapter.getInstance(world.getRealm(id));
69 | } catch (org.codehaus.plexus.classworlds.realm.NoSuchRealmException e) {
70 | throw new NoSuchRealmException(this, e.getId());
71 | }
72 | }
73 |
74 | public Collection getRealms() {
75 | Collection realms = world.getRealms();
76 | Vector ret = new Vector<>();
77 | for (org.codehaus.plexus.classworlds.realm.ClassRealm classRealm : realms) {
78 | ret.add(ClassRealmAdapter.getInstance(classRealm));
79 | }
80 |
81 | return ret;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/NoSuchRealmException.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 |
5 | Copyright 2002 (C) The Werken Company. All Rights Reserved.
6 |
7 | Redistribution and use of this software and associated documentation
8 | ("Software"), with or without modification, are permitted provided
9 | that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain copyright
12 | statements and notices. Redistributions must also contain a
13 | copy of this document.
14 |
15 | 2. Redistributions in binary form must reproduce the
16 | above copyright notice, this list of conditions and the
17 | following disclaimer in the documentation and/or other
18 | materials provided with the distribution.
19 |
20 | 3. The name "classworlds" must not be used to endorse or promote
21 | products derived from this Software without prior written
22 | permission of The Werken Company. For written permission,
23 | please contact bob@werken.com.
24 |
25 | 4. Products derived from this Software may not be called "classworlds"
26 | nor may "classworlds" appear in their names without prior written
27 | permission of The Werken Company. "classworlds" is a registered
28 | trademark of The Werken Company.
29 |
30 | 5. Due credit should be given to The Werken Company.
31 | (http://classworlds.werken.com/).
32 |
33 | THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
34 | ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
35 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
37 | THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
42 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
44 | OF THE POSSIBILITY OF SUCH DAMAGE.
45 |
46 | */
47 |
48 | /**
49 | * Indicates an attempt to retrieve a ClassRealm from a
50 | * ClassWorld with an invalid id.
51 | *
52 | * @author bob mcwhirter
53 | */
54 | @Deprecated
55 | public class NoSuchRealmException extends ClassWorldException {
56 | // ------------------------------------------------------------
57 | // Instance members
58 | // ------------------------------------------------------------
59 |
60 | /**
61 | * The realm id.
62 | */
63 | private final String id;
64 |
65 | // ------------------------------------------------------------
66 | // Constructors
67 | // ------------------------------------------------------------
68 |
69 | /**
70 | * Construct.
71 | *
72 | * @param world The world.
73 | * @param id The realm id.
74 | */
75 | public NoSuchRealmException(ClassWorld world, String id) {
76 | super(world, id);
77 | this.id = id;
78 | }
79 |
80 | // ------------------------------------------------------------
81 | // Instance methods
82 | // ------------------------------------------------------------
83 |
84 | /**
85 | * Retrieve the invalid realm id.
86 | *
87 | * @return The id.
88 | */
89 | public String getId() {
90 | return this.id;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/DuplicateRealmException.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 |
5 | Copyright 2002 (C) The Werken Company. All Rights Reserved.
6 |
7 | Redistribution and use of this software and associated documentation
8 | ("Software"), with or without modification, are permitted provided
9 | that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain copyright
12 | statements and notices. Redistributions must also contain a
13 | copy of this document.
14 |
15 | 2. Redistributions in binary form must reproduce the
16 | above copyright notice, this list of conditions and the
17 | following disclaimer in the documentation and/or other
18 | materials provided with the distribution.
19 |
20 | 3. The name "classworlds" must not be used to endorse or promote
21 | products derived from this Software without prior written
22 | permission of The Werken Company. For written permission,
23 | please contact bob@werken.com.
24 |
25 | 4. Products derived from this Software may not be called "classworlds"
26 | nor may "classworlds" appear in their names without prior written
27 | permission of The Werken Company. "classworlds" is a registered
28 | trademark of The Werken Company.
29 |
30 | 5. Due credit should be given to The Werken Company.
31 | (http://classworlds.werken.com/).
32 |
33 | THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
34 | ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
35 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
37 | THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
42 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
44 | OF THE POSSIBILITY OF SUCH DAMAGE.
45 |
46 | */
47 |
48 | /**
49 | * Indicates an attempt to add a ClassRealm to a
50 | * ClassWorld with a duplicate id.
51 | *
52 | * @author bob mcwhirter
53 | */
54 | @Deprecated
55 | public class DuplicateRealmException extends ClassWorldException {
56 | // ------------------------------------------------------------
57 | // Instance members
58 | // ------------------------------------------------------------
59 |
60 | /**
61 | * The realm id.
62 | */
63 | private final String id;
64 |
65 | // ------------------------------------------------------------
66 | // Constructors
67 | // ------------------------------------------------------------
68 |
69 | /**
70 | * Construct.
71 | *
72 | * @param world The world.
73 | * @param id The realm id.
74 | */
75 | public DuplicateRealmException(ClassWorld world, String id) {
76 | super(world, id);
77 | this.id = id;
78 | }
79 |
80 | // ------------------------------------------------------------
81 | // Instance methods
82 | // ------------------------------------------------------------
83 |
84 | /**
85 | * Retrieve the duplicate realm id.
86 | *
87 | * @return The id.
88 | */
89 | public String getId() {
90 | return this.id;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ClassWorldException.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 |
5 | Copyright 2002 (C) The Werken Company. All Rights Reserved.
6 |
7 | Redistribution and use of this software and associated documentation
8 | ("Software"), with or without modification, are permitted provided
9 | that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain copyright
12 | statements and notices. Redistributions must also contain a
13 | copy of this document.
14 |
15 | 2. Redistributions in binary form must reproduce the
16 | above copyright notice, this list of conditions and the
17 | following disclaimer in the documentation and/or other
18 | materials provided with the distribution.
19 |
20 | 3. The name "classworlds" must not be used to endorse or promote
21 | products derived from this Software without prior written
22 | permission of The Werken Company. For written permission,
23 | please contact bob@werken.com.
24 |
25 | 4. Products derived from this Software may not be called "classworlds"
26 | nor may "classworlds" appear in their names without prior written
27 | permission of The Werken Company. "classworlds" is a registered
28 | trademark of The Werken Company.
29 |
30 | 5. Due credit should be given to The Werken Company.
31 | (http://classworlds.werken.com/).
32 |
33 | THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
34 | ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
35 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
37 | THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
42 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
44 | OF THE POSSIBILITY OF SUCH DAMAGE.
45 |
46 | */
47 |
48 | /**
49 | * Base exception for ClassWorld errors.
50 | *
51 | * @author bob mcwhirter
52 | */
53 | @Deprecated
54 | public class ClassWorldException extends Exception {
55 | // ------------------------------------------------------------
56 | // Instance members
57 | // ------------------------------------------------------------
58 |
59 | /**
60 | * The world.
61 | */
62 | private final ClassWorld world;
63 |
64 | // ------------------------------------------------------------
65 | // Constructors
66 | // ------------------------------------------------------------
67 |
68 | /**
69 | * Construct.
70 | *
71 | * @param world The world.
72 | */
73 | public ClassWorldException(final ClassWorld world) {
74 | this.world = world;
75 | }
76 |
77 | /**
78 | * Construct.
79 | *
80 | * @param world The world.
81 | * @param msg The detail message.
82 | */
83 | public ClassWorldException(final ClassWorld world, final String msg) {
84 | super(msg);
85 | this.world = world;
86 | }
87 |
88 | // ------------------------------------------------------------
89 | // Instance methods
90 | // ------------------------------------------------------------
91 |
92 | /**
93 | * Retrieve the world.
94 | *
95 | * @return The world.
96 | */
97 | public ClassWorld getWorld() {
98 | return this.world;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ClassWorldReverseAdapter.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.util.Collection;
20 | import java.util.HashMap;
21 | import java.util.Vector;
22 |
23 | /**
24 | * A reverse adapter for ClassWorlds
25 | *
26 | * @author Andrew Williams
27 | */
28 | @SuppressWarnings({"unchecked", "rawtypes"})
29 | @Deprecated
30 | public class ClassWorldReverseAdapter extends org.codehaus.plexus.classworlds.ClassWorld {
31 | private static final HashMap instances = new HashMap();
32 |
33 | public static ClassWorldReverseAdapter getInstance(ClassWorld oldWorld) {
34 | if (instances.containsKey(oldWorld)) return (ClassWorldReverseAdapter) instances.get(oldWorld);
35 |
36 | ClassWorldReverseAdapter adapter = new ClassWorldReverseAdapter(oldWorld);
37 | instances.put(oldWorld, adapter);
38 |
39 | return adapter;
40 | }
41 |
42 | private final ClassWorld world;
43 |
44 | private ClassWorldReverseAdapter(ClassWorld newWorld) {
45 | super();
46 | this.world = newWorld;
47 | }
48 |
49 | public org.codehaus.plexus.classworlds.realm.ClassRealm newRealm(String id)
50 | throws org.codehaus.plexus.classworlds.realm.DuplicateRealmException {
51 | try {
52 | return ClassRealmReverseAdapter.getInstance(world.newRealm(id));
53 | } catch (DuplicateRealmException e) {
54 | throw new org.codehaus.plexus.classworlds.realm.DuplicateRealmException(this, e.getId());
55 | }
56 | }
57 |
58 | public org.codehaus.plexus.classworlds.realm.ClassRealm newRealm(String id, ClassLoader classLoader)
59 | throws org.codehaus.plexus.classworlds.realm.DuplicateRealmException {
60 | try {
61 | return ClassRealmReverseAdapter.getInstance(world.newRealm(id, classLoader));
62 | } catch (DuplicateRealmException e) {
63 | throw new org.codehaus.plexus.classworlds.realm.DuplicateRealmException(this, e.getId());
64 | }
65 | }
66 |
67 | public void disposeRealm(String id) throws org.codehaus.plexus.classworlds.realm.NoSuchRealmException {
68 | try {
69 | world.disposeRealm(id);
70 | } catch (NoSuchRealmException e) {
71 | throw new org.codehaus.plexus.classworlds.realm.NoSuchRealmException(this, e.getId());
72 | }
73 | }
74 |
75 | public org.codehaus.plexus.classworlds.realm.ClassRealm getRealm(String id)
76 | throws org.codehaus.plexus.classworlds.realm.NoSuchRealmException {
77 | try {
78 | return ClassRealmReverseAdapter.getInstance(world.getRealm(id));
79 | } catch (NoSuchRealmException e) {
80 | throw new org.codehaus.plexus.classworlds.realm.NoSuchRealmException(this, e.getId());
81 | }
82 | }
83 |
84 | public Collection getRealms() {
85 | Collection realms = world.getRealms();
86 | Vector ret = new Vector();
87 |
88 | for (Object o : realms) {
89 | ClassRealm realm = (ClassRealm) o;
90 | ret.add(ClassRealmReverseAdapter.getInstance(realm));
91 | }
92 |
93 | return ret;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ClassRealm.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 |
5 | Copyright 2002 (C) The Werken Company. All Rights Reserved.
6 |
7 | Redistribution and use of this software and associated documentation
8 | ("Software"), with or without modification, are permitted provided
9 | that the following conditions are met:
10 |
11 | 1. Redistributions of source code must retain copyright
12 | statements and notices. Redistributions must also contain a
13 | copy of this document.
14 |
15 | 2. Redistributions in binary form must reproduce the
16 | above copyright notice, this list of conditions and the
17 | following disclaimer in the documentation and/or other
18 | materials provided with the distribution.
19 |
20 | 3. The name "classworlds" must not be used to endorse or promote
21 | products derived from this Software without prior written
22 | permission of The Werken Company. For written permission,
23 | please contact bob@werken.com.
24 |
25 | 4. Products derived from this Software may not be called "classworlds"
26 | nor may "classworlds" appear in their names without prior written
27 | permission of The Werken Company. "classworlds" is a registered
28 | trademark of The Werken Company.
29 |
30 | 5. Due credit should be given to The Werken Company.
31 | (http://classworlds.werken.com/).
32 |
33 | THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
34 | ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
35 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
37 | THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
42 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
44 | OF THE POSSIBILITY OF SUCH DAMAGE.
45 |
46 | */
47 |
48 | import java.io.IOException;
49 | import java.io.InputStream;
50 | import java.net.URL;
51 | import java.util.Enumeration;
52 |
53 | /**
54 | *
Autonomous sub-portion of a ClassWorld.
55 | *
56 | *
This class most closed maps to the ClassLoader
57 | * role from Java and in facts can provide a ClassLoader
58 | * view of itself using {@link #getClassLoader}.
59 | *
60 | * @author bob mcwhirter
61 | * @author Jason van Zyl
62 | */
63 | @SuppressWarnings("rawtypes")
64 | @Deprecated
65 | public interface ClassRealm {
66 | String getId();
67 |
68 | ClassWorld getWorld();
69 |
70 | void importFrom(String realmId, String pkgName) throws NoSuchRealmException;
71 |
72 | void addConstituent(URL constituent);
73 |
74 | ClassRealm locateSourceRealm(String className);
75 |
76 | void setParent(ClassRealm classRealm);
77 |
78 | ClassRealm createChildRealm(String id) throws DuplicateRealmException;
79 |
80 | ClassLoader getClassLoader();
81 |
82 | ClassRealm getParent();
83 |
84 | URL[] getConstituents();
85 |
86 | // ----------------------------------------------------------------------
87 | // Classloading
88 | // ----------------------------------------------------------------------
89 |
90 | Class loadClass(String name) throws ClassNotFoundException;
91 |
92 | // ----------------------------------------------------------------------
93 | // Resource handling
94 | // ----------------------------------------------------------------------
95 |
96 | URL getResource(String name);
97 |
98 | Enumeration findResources(String name) throws IOException;
99 |
100 | InputStream getResourceAsStream(String name);
101 |
102 | void display();
103 | }
104 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/ClassView.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | public class ClassView {
20 | /**
21 | * * Formats Class information for debug output purposes.
22 | * *
23 | * * @param clz the Class to print information for
24 | * *
25 | * * @return a String describing the Class in detail
26 | */
27 | public static String toString(Class> clz) {
28 | if (clz.isPrimitive()) {
29 | return clz.toString();
30 | } else if (clz.isArray()) {
31 | return "Array of " + toString(clz.getComponentType());
32 | } else if (clz.isInterface()) {
33 | return toInterfaceString(clz, "");
34 | } else {
35 | return toClassString(clz, "");
36 | }
37 | }
38 |
39 | /**
40 | * * Formats Class information for debug output purposes.
41 | * *
42 | * * @param clz the Class to print information for
43 | * * @param sIndent the indentation to precede each line of output
44 | * *
45 | * * @return a String describing the Class in detail
46 | */
47 | private static String toClassString(Class> clz, String sIndent) {
48 | StringBuilder sb = new StringBuilder();
49 | sb.append(sIndent)
50 | .append("Class ")
51 | .append(clz.getName())
52 | .append(" (")
53 | .append(toString(clz.getClassLoader()))
54 | .append(')');
55 |
56 | sIndent += " ";
57 |
58 | Class>[] aclz = clz.getInterfaces();
59 | for (Class> aClass : aclz) {
60 | sb.append('\n').append(toInterfaceString(aClass, sIndent));
61 | }
62 |
63 | clz = clz.getSuperclass();
64 | if (clz != null) {
65 | sb.append('\n').append(toClassString(clz, sIndent));
66 | }
67 |
68 | return sb.toString();
69 | }
70 |
71 | /**
72 | * * Formats interface information for debug output purposes.
73 | * *
74 | * * @param clz the interface Class to print information for
75 | * * @param sIndent the indentation to precede each line of output
76 | * *
77 | * * @return a String describing the interface Class in detail
78 | */
79 | private static String toInterfaceString(Class> clz, String sIndent) {
80 | StringBuilder sb = new StringBuilder();
81 | sb.append(sIndent)
82 | .append("Interface ")
83 | .append(clz.getName())
84 | .append(" (")
85 | .append(toString(clz.getClassLoader()))
86 | .append(')');
87 |
88 | Class>[] aclz = clz.getInterfaces();
89 | for (Class> aClass : aclz) {
90 | clz = aClass;
91 |
92 | sb.append('\n').append(toInterfaceString(clz, sIndent + " "));
93 | }
94 |
95 | return sb.toString();
96 | }
97 |
98 | /**
99 | * * Format a description for the specified ClassLoader object.
100 | * *
101 | * * @param loader the ClassLoader instance (or null)
102 | * *
103 | * * @return a String description of the ClassLoader
104 | */
105 | private static String toString(ClassLoader loader) {
106 | if (loader == null) {
107 | return "System ClassLoader";
108 | }
109 |
110 | return "ClassLoader class=" + loader.getClass().getName() + ", hashCode=" + loader.hashCode();
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/launcher/LauncherTest.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.launcher;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | import java.io.File;
19 | import java.io.FileInputStream;
20 |
21 | import org.codehaus.plexus.classworlds.AbstractClassWorldsTestCase;
22 | import org.codehaus.plexus.classworlds.TestUtil;
23 | import org.junit.jupiter.api.AfterEach;
24 | import org.junit.jupiter.api.BeforeEach;
25 | import org.junit.jupiter.api.Test;
26 |
27 | import static org.junit.jupiter.api.Assertions.assertEquals;
28 | import static org.junit.jupiter.api.Assertions.assertNotNull;
29 | import static org.junit.jupiter.api.Assertions.fail;
30 |
31 | class LauncherTest extends AbstractClassWorldsTestCase {
32 | private Launcher launcher;
33 |
34 | @BeforeEach
35 | void setUp() {
36 | System.setProperty("java.protocol.handler.pkgs", "org.codehaus.classworlds.protocol");
37 |
38 | this.launcher = new Launcher();
39 |
40 | this.launcher.setSystemClassLoader(Thread.currentThread().getContextClassLoader());
41 | }
42 |
43 | @AfterEach
44 | void tearDown() {
45 | this.launcher = null;
46 | }
47 |
48 | @Test
49 | void configureValid() throws Exception {
50 | launcher.configure(getConfigPath("valid-launch.conf"));
51 |
52 | Class> mainClass = launcher.getMainClass();
53 |
54 | assertNotNull(mainClass);
55 |
56 | assertEquals("a.A", mainClass.getName());
57 |
58 | assertEquals("app", launcher.getMainRealm().getId());
59 | }
60 |
61 | @Test
62 | void launchValidStandard() throws Exception {
63 | launcher.configure(getConfigPath("valid-launch.conf"));
64 |
65 | launcher.launch(new String[] {});
66 | }
67 |
68 | @Test
69 | void launchValidStandardExitCode() throws Exception {
70 | launcher.configure(getConfigPath("valid-launch-exitCode.conf"));
71 |
72 | launcher.launch(new String[] {});
73 |
74 | assertEquals(15, launcher.getExitCode(), "check exit code");
75 | }
76 |
77 | @Test
78 | void launchValidEnhanced() throws Exception {
79 | launcher.configure(getConfigPath("valid-enh-launch.conf"));
80 |
81 | launcher.launch(new String[] {});
82 | }
83 |
84 | @Test
85 | void launchValidEnhancedExitCode() throws Exception {
86 | launcher.configure(getConfigPath("valid-enh-launch-exitCode.conf"));
87 |
88 | launcher.launch(new String[] {});
89 |
90 | assertEquals(45, launcher.getExitCode(), "check exit code");
91 | }
92 |
93 | @Test
94 | void launchNoSuchMethod() throws Exception {
95 | launcher.configure(getConfigPath("launch-nomethod.conf"));
96 |
97 | try {
98 | launcher.launch(new String[] {});
99 | fail("should have thrown NoSuchMethodException");
100 | } catch (NoSuchMethodException e) {
101 | // expected and correct
102 | }
103 | }
104 |
105 | @Test
106 | void launchClassNotFound() throws Exception {
107 | launcher.configure(getConfigPath("launch-noclass.conf"));
108 |
109 | try {
110 | launcher.launch(new String[] {});
111 | fail("throw ClassNotFoundException");
112 | } catch (ClassNotFoundException e) {
113 | // expected and correct
114 | }
115 | }
116 |
117 | private FileInputStream getConfigPath(String name) throws Exception {
118 | String basedir = TestUtil.getBasedir();
119 |
120 | return new FileInputStream(new File(new File(basedir, "src/test/test-data"), name));
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ClassRealmReverseAdapter.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.net.URL;
22 | import java.util.Enumeration;
23 |
24 | /**
25 | * A reverse adapter for ClassRealms
26 | *
27 | * @author Andrew Williams
28 | */
29 | @SuppressWarnings({"UnnecessaryLocalVariable", "rawtypes"})
30 | @Deprecated
31 | public class ClassRealmReverseAdapter extends org.codehaus.plexus.classworlds.realm.ClassRealm {
32 |
33 | public static ClassRealmReverseAdapter getInstance(ClassRealm oldRealm) {
34 | ClassRealmReverseAdapter adapter = new ClassRealmReverseAdapter(oldRealm);
35 |
36 | return adapter;
37 | }
38 |
39 | private final ClassRealm realm;
40 |
41 | private ClassRealmReverseAdapter(ClassRealm oldRealm) {
42 | super(ClassWorldReverseAdapter.getInstance(oldRealm.getWorld()), oldRealm.getId(), oldRealm.getClassLoader());
43 | this.realm = oldRealm;
44 | }
45 |
46 | public String getId() {
47 | return realm.getId();
48 | }
49 |
50 | public org.codehaus.plexus.classworlds.ClassWorld getWorld() {
51 | return ClassWorldReverseAdapter.getInstance(realm.getWorld());
52 | }
53 |
54 | public void importFrom(String realmId, String pkgName)
55 | throws org.codehaus.plexus.classworlds.realm.NoSuchRealmException {
56 | try {
57 | realm.importFrom(realmId, pkgName);
58 | } catch (NoSuchRealmException e) {
59 | throw new org.codehaus.plexus.classworlds.realm.NoSuchRealmException(getWorld(), e.getId());
60 | }
61 | }
62 |
63 | public void addURL(URL constituent) {
64 | realm.addConstituent(constituent);
65 | }
66 |
67 | public org.codehaus.plexus.classworlds.realm.ClassRealm locateSourceRealm(String className) {
68 | return getInstance(realm.locateSourceRealm(className));
69 | }
70 |
71 | public void setParentRealm(org.codehaus.plexus.classworlds.realm.ClassRealm classRealm) {
72 | realm.setParent(ClassRealmAdapter.getInstance(classRealm));
73 | }
74 |
75 | public org.codehaus.plexus.classworlds.realm.ClassRealm createChildRealm(String id)
76 | throws org.codehaus.plexus.classworlds.realm.DuplicateRealmException {
77 | try {
78 | return getInstance(realm.createChildRealm(id));
79 | } catch (DuplicateRealmException e) {
80 | throw new org.codehaus.plexus.classworlds.realm.DuplicateRealmException(getWorld(), e.getId());
81 | }
82 | }
83 |
84 | public ClassLoader getClassLoader() {
85 | return realm.getClassLoader();
86 | }
87 |
88 | public org.codehaus.plexus.classworlds.realm.ClassRealm getParentRealm() {
89 | return getInstance(realm.getParent());
90 | }
91 |
92 | public URL[] getURLs() {
93 | return realm.getConstituents();
94 | }
95 |
96 | public Class loadClass(String name) throws ClassNotFoundException {
97 | return realm.loadClass(name);
98 | }
99 |
100 | public URL getResource(String name) {
101 | return realm.getResource(name);
102 | }
103 |
104 | @SuppressWarnings("unchecked")
105 | public Enumeration findResources(String name) throws IOException {
106 | return realm.findResources(name);
107 | }
108 |
109 | public InputStream getResourceAsStream(String name) {
110 | return realm.getResourceAsStream(name);
111 | }
112 |
113 | public void display() {
114 | realm.display();
115 | }
116 |
117 | public boolean equals(Object o) {
118 | if (!(o instanceof ClassRealm)) return false;
119 |
120 | return getId().equals(((ClassRealm) o).getId());
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/strategy/StrategyTest.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.strategy;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | import java.io.InputStream;
19 | import java.net.URL;
20 | import java.util.Enumeration;
21 |
22 | import org.codehaus.plexus.classworlds.AbstractClassWorldsTestCase;
23 | import org.codehaus.plexus.classworlds.ClassWorld;
24 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
25 | import org.junit.jupiter.api.BeforeEach;
26 | import org.junit.jupiter.api.Test;
27 |
28 | import static org.junit.jupiter.api.Assertions.assertEquals;
29 | import static org.junit.jupiter.api.Assertions.assertNotNull;
30 | import static org.junit.jupiter.api.Assertions.assertTrue;
31 | import static org.junit.jupiter.api.Assertions.fail;
32 | import static org.junit.jupiter.api.Assumptions.assumeTrue;
33 |
34 | // jars within jars
35 | // hierarchy vs graph
36 |
37 | class StrategyTest extends AbstractClassWorldsTestCase {
38 | private ClassRealm realm;
39 |
40 | private Strategy strategy;
41 |
42 | @BeforeEach
43 | void setUp() throws Exception {
44 | //noinspection resource
45 | this.realm = new ClassWorld().newRealm("realm");
46 | this.strategy = this.realm.getStrategy();
47 | realm.addURL(getJarUrl("component0-1.0.jar"));
48 | }
49 |
50 | @Test
51 | void loadingOfApplicationClass() throws Exception {
52 | assertNotNull(strategy.loadClass("org.codehaus.plexus.Component0"));
53 | }
54 |
55 | @Test
56 | void loadingOfApplicationClassThenDoingItAgain() throws Exception {
57 | Class> c = strategy.loadClass("org.codehaus.plexus.Component0");
58 |
59 | assertNotNull(c);
60 |
61 | c = strategy.loadClass("org.codehaus.plexus.Component0");
62 |
63 | assertNotNull(c);
64 | }
65 |
66 | @Test
67 | void loadingOfSystemClass() throws Exception {
68 | assertNotNull(strategy.getRealm().loadClass("java.lang.Object"));
69 | }
70 |
71 | @Test
72 | void loadingOfNonExistentClass() {
73 | try {
74 | strategy.loadClass("org.codehaus.plexus.NonExistentComponent");
75 |
76 | fail("Should have thrown a ClassNotFoundException!");
77 | } catch (ClassNotFoundException e) {
78 | // do nothing
79 | }
80 | }
81 |
82 | @Test
83 | void getApplicationResource() throws Exception {
84 | URL resource = strategy.getResource("META-INF/plexus/components.xml");
85 |
86 | assertNotNull(resource);
87 |
88 | String content = getContent(resource.openStream());
89 |
90 | assertTrue(content.startsWith(""));
91 | }
92 |
93 | @Test
94 | void getSystemResource() {
95 | assumeTrue(
96 | getJavaVersion() < 9.0,
97 | "Due to strong encapsulation you cannot get the java/lang/Object.class as resource since Java 9");
98 |
99 | URL resource = strategy.getRealm().getResource("java/lang/Object.class");
100 |
101 | assertNotNull(resource);
102 | }
103 |
104 | @Test
105 | void findResources() throws Exception {
106 | realm.addURL(getJarUrl("component1-1.0.jar"));
107 |
108 | Enumeration e = strategy.getResources("META-INF/plexus/components.xml");
109 | assertNotNull(e);
110 |
111 | int resourceCount = 0;
112 | while (e.hasMoreElements()) {
113 | e.nextElement();
114 | resourceCount++;
115 | }
116 | assertEquals(2, resourceCount);
117 | }
118 |
119 | protected String getContent(InputStream in) throws Exception {
120 | byte[] buffer = new byte[1024];
121 |
122 | int read;
123 |
124 | StringBuilder content = new StringBuilder();
125 |
126 | while ((read = in.read(buffer, 0, 1024)) >= 0) {
127 | content.append(new String(buffer, 0, read));
128 | }
129 |
130 | return content.toString();
131 | }
132 |
133 | private double getJavaVersion() {
134 | return Double.parseDouble(System.getProperty("java.specification.version"));
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/realm/FilteredClassRealmTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.codehaus.plexus.classworlds.realm;
20 |
21 | import java.util.HashSet;
22 | import java.util.Set;
23 | import java.util.function.Predicate;
24 |
25 | import org.codehaus.plexus.classworlds.AbstractClassWorldsTestCase;
26 | import org.codehaus.plexus.classworlds.ClassWorld;
27 | import org.junit.jupiter.api.BeforeEach;
28 | import org.junit.jupiter.api.Test;
29 |
30 | import static org.junit.jupiter.api.Assertions.assertFalse;
31 | import static org.junit.jupiter.api.Assertions.assertNotNull;
32 | import static org.junit.jupiter.api.Assertions.assertNull;
33 | import static org.junit.jupiter.api.Assertions.assertThrows;
34 | import static org.junit.jupiter.api.Assertions.assertTrue;
35 |
36 | class FilteredClassRealmTest extends AbstractClassWorldsTestCase {
37 | private ClassWorld world;
38 | private ClassRealm realmA;
39 |
40 | @BeforeEach
41 | void setUp() throws DuplicateRealmException {
42 | this.world = new ClassWorld();
43 | // only allow loading resources whose names start with "a."
44 | Set allowedResourcePrefixes = new HashSet<>();
45 | allowedResourcePrefixes.add("a.");
46 | allowedResourcePrefixes.add("a/Aa");
47 | realmA = this.world.newRealm("realmA", getClass().getClassLoader(), s -> allowedResourcePrefixes.stream()
48 | .anyMatch(s::startsWith));
49 | }
50 |
51 | @Test
52 | void loadResources() throws Exception {
53 | realmA.addURL(getJarUrl("a.jar"));
54 | assertNull(realmA.getResource("common.properties"));
55 | assertFalse(realmA.getResources("common.properties").hasMoreElements());
56 |
57 | assertNotNull(realmA.getResource("a.properties"));
58 | assertTrue(realmA.getResources("a.properties").hasMoreElements());
59 | }
60 |
61 | @Test
62 | void loadClass() throws Exception {
63 | assertThrows(ClassNotFoundException.class, () -> realmA.loadClass("a.Aa"));
64 | realmA.addURL(getJarUrl("a.jar"));
65 |
66 | assertNotNull(realmA.loadClass("a.Aa"));
67 | assertThrows(ClassNotFoundException.class, () -> realmA.loadClass("a.A"));
68 |
69 | assertNotNull(realmA.loadClass("a.Aa"));
70 | assertThrows(ClassNotFoundException.class, () -> realmA.loadClass("a.A"));
71 | }
72 |
73 | @Test
74 | void loadClassWithModule() throws Exception {
75 | try (ExtendedFilteredClassRealm realmA = new ExtendedFilteredClassRealm(world, s -> s.startsWith("a/Aa"))) {
76 | realmA.addURL(getJarUrl("a.jar"));
77 | assertNotNull(realmA.simulateLoadClassFromModule("a.Aa"));
78 | assertNull(realmA.simulateLoadClassFromModule("a.A"));
79 | }
80 | }
81 |
82 | /**
83 | * Simulates new {@code java.lang.ClassLoader#findClass(String,String)} introduced with Java 9.
84 | * It is reversed in terms of inheritance but enables to simulate the same behavior in these tests.
85 | * @see ClassLoader#findClass(String,String)
86 | * @see ClassRealmImplTest.ExtendedClassRealm
87 | */
88 | static class ExtendedFilteredClassRealm extends FilteredClassRealm {
89 |
90 | public ExtendedFilteredClassRealm(final ClassWorld world, Predicate filter) {
91 | super(filter, world, "java9", Thread.currentThread().getContextClassLoader());
92 | }
93 |
94 | public Class> simulateLoadClassFromModule(final String name) {
95 | synchronized (getClassLoadingLock(name)) {
96 | Class> c = findLoadedClass(name);
97 | if (c == null) {
98 | c = findClass(null, name);
99 | }
100 | return c;
101 | }
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/ClassRealmAdapter.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.net.URL;
22 | import java.util.Enumeration;
23 |
24 | /**
25 | * An adapter for ClassRealms
26 | *
27 | * @author Andrew Williams
28 | */
29 | @SuppressWarnings({"UnnecessaryLocalVariable", "DeprecatedIsStillUsed", "rawtypes"})
30 | @Deprecated
31 | public class ClassRealmAdapter implements ClassRealm {
32 |
33 | public static ClassRealmAdapter getInstance(org.codehaus.plexus.classworlds.realm.ClassRealm newRealm) {
34 | ClassRealmAdapter adapter = new ClassRealmAdapter(newRealm);
35 |
36 | return adapter;
37 | }
38 |
39 | private final org.codehaus.plexus.classworlds.realm.ClassRealm realm;
40 |
41 | private ClassRealmAdapter(org.codehaus.plexus.classworlds.realm.ClassRealm newRealm) {
42 | this.realm = newRealm;
43 | }
44 |
45 | public String getId() {
46 | return realm.getId();
47 | }
48 |
49 | public ClassWorld getWorld() {
50 | return ClassWorldAdapter.getInstance(realm.getWorld());
51 | }
52 |
53 | public void importFrom(String realmId, String pkgName) throws NoSuchRealmException {
54 | try {
55 | realm.importFrom(realmId, pkgName);
56 | } catch (org.codehaus.plexus.classworlds.realm.NoSuchRealmException e) {
57 | throw new NoSuchRealmException(getWorld(), e.getId());
58 | }
59 | }
60 |
61 | public void addConstituent(URL constituent) {
62 | realm.addURL(constituent);
63 | }
64 |
65 | public ClassRealm locateSourceRealm(String className) {
66 | ClassLoader importLoader = realm.getImportClassLoader(className);
67 |
68 | if (importLoader instanceof org.codehaus.plexus.classworlds.realm.ClassRealm) {
69 | return ClassRealmAdapter.getInstance((org.codehaus.plexus.classworlds.realm.ClassRealm) importLoader);
70 | } else {
71 | return null;
72 | }
73 | }
74 |
75 | public void setParent(ClassRealm classRealm) {
76 | if (classRealm != null) {
77 | realm.setParentRealm(ClassRealmReverseAdapter.getInstance(classRealm));
78 | }
79 | }
80 |
81 | public ClassRealm createChildRealm(String id) throws DuplicateRealmException {
82 | try {
83 | return ClassRealmAdapter.getInstance(realm.createChildRealm(id));
84 | } catch (org.codehaus.plexus.classworlds.realm.DuplicateRealmException e) {
85 | throw new DuplicateRealmException(getWorld(), e.getId());
86 | }
87 | }
88 |
89 | public ClassLoader getClassLoader() {
90 | return realm;
91 | }
92 |
93 | public ClassRealm getParent() {
94 | return ClassRealmAdapter.getInstance(realm.getParentRealm());
95 | }
96 |
97 | public ClassRealm getParentRealm() {
98 | return ClassRealmAdapter.getInstance(realm.getParentRealm());
99 | }
100 |
101 | public URL[] getConstituents() {
102 | return realm.getURLs();
103 | }
104 |
105 | public Class loadClass(String name) throws ClassNotFoundException {
106 | return realm.loadClass(name);
107 | }
108 |
109 | public URL getResource(String name) {
110 | return realm.getResource(trimLeadingSlash(name));
111 | }
112 |
113 | public Enumeration findResources(String name) throws IOException {
114 | return realm.findResources(trimLeadingSlash(name));
115 | }
116 |
117 | public InputStream getResourceAsStream(String name) {
118 | return realm.getResourceAsStream(trimLeadingSlash(name));
119 | }
120 |
121 | public void display() {
122 | realm.display();
123 | }
124 |
125 | public boolean equals(Object o) {
126 | if (!(o instanceof ClassRealm)) return false;
127 |
128 | return getId().equals(((ClassRealm) o).getId());
129 | }
130 |
131 | /**
132 | * Provides backward-compat with the old classworlds which accepted resource names with leading slashes.
133 | */
134 | private String trimLeadingSlash(String resource) {
135 | if (resource != null && resource.startsWith("/")) {
136 | return resource.substring(1);
137 | } else {
138 | return resource;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/Configurator.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.FileNotFoundException;
20 | import java.io.IOException;
21 | import java.io.InputStream;
22 | import java.net.MalformedURLException;
23 |
24 | /**
25 | * A compatibility wrapper for org.codehaus.plexus.classworlds.launcher.Configurator
26 | * provided for legacy code
27 | *
28 | * @author Andrew Williams
29 | */
30 | @Deprecated
31 | public class Configurator {
32 | private final ConfiguratorAdapter config;
33 |
34 | /** Construct.
35 | *
36 | * @param launcher The launcher to configure.
37 | */
38 | public Configurator(Launcher launcher) {
39 | config = ConfiguratorAdapter.getInstance(
40 | new org.codehaus.plexus.classworlds.launcher.Configurator(launcher), launcher);
41 | }
42 |
43 | /** Construct.
44 | *
45 | * @param world The classWorld to configure.
46 | */
47 | public Configurator(ClassWorld world) {
48 | config = ConfiguratorAdapter.getInstance(
49 | new org.codehaus.plexus.classworlds.launcher.Configurator(ClassWorldReverseAdapter.getInstance(world)),
50 | world);
51 | }
52 |
53 | /** set world.
54 | * this setter is provided so you can use the same configurator to configure several "worlds"
55 | *
56 | * @param world The classWorld to configure.
57 | */
58 | public void setClassWorld(ClassWorld world) {
59 | config.setClassWorld(world);
60 | }
61 |
62 | /**
63 | * Configure from a file.
64 | *
65 | * @param is The config input stream
66 | * @throws IOException If an error occurs reading the config file.
67 | * @throws MalformedURLException If the config file contains invalid URLs.
68 | * @throws ConfigurationException If the config file is corrupt.
69 | * @throws DuplicateRealmException If the config file defines two realms with the same id.
70 | * @throws NoSuchRealmException If the config file defines a main entry point in
71 | * a non-existent realm.
72 | */
73 | public void configure(InputStream is)
74 | throws IOException, MalformedURLException, ConfigurationException, DuplicateRealmException,
75 | NoSuchRealmException {
76 | config.configureAdapter(is);
77 | }
78 |
79 | /**
80 | * Associate parent realms with their children.
81 | */
82 | protected void associateRealms() {
83 | config.associateRealms();
84 | }
85 |
86 | /**
87 | * Load a glob into the specified classloader.
88 | *
89 | * @param line The path configuration line.
90 | * @param realm The realm to populate
91 | * @throws MalformedURLException If the line does not represent
92 | * a valid path element.
93 | * @throws FileNotFoundException If the line does not represent
94 | * a valid path element in the filesystem.
95 | */
96 | protected void loadGlob(String line, ClassRealm realm) throws MalformedURLException, FileNotFoundException {
97 | loadGlob(line, realm, false);
98 | }
99 |
100 | /**
101 | * Load a glob into the specified classloader.
102 | *
103 | * @param line The path configuration line.
104 | * @param realm The realm to populate
105 | * @param optionally Whether the path is optional or required
106 | * @throws MalformedURLException If the line does not represent
107 | * a valid path element.
108 | * @throws FileNotFoundException If the line does not represent
109 | * a valid path element in the filesystem.
110 | */
111 | @SuppressWarnings("RedundantThrows")
112 | protected void loadGlob(String line, ClassRealm realm, boolean optionally)
113 | throws MalformedURLException, FileNotFoundException {
114 | config.loadGlob(line, realm, optionally);
115 | }
116 |
117 | /**
118 | * Filter a string for system properties.
119 | *
120 | * @param text The text to filter.
121 | * @return The filtered text.
122 | * @throws ConfigurationException If the property does not
123 | * exist or if there is a syntax error.
124 | */
125 | @SuppressWarnings("RedundantThrows")
126 | protected String filter(String text) throws ConfigurationException {
127 | return config.filter(text);
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/classworlds/DefaultClassRealm.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2010 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /*
20 | * A compatibility wrapper for org.codehaus.plexus.classworlds.realm.ClassRealm
21 | * provided for legacy code
22 | *
23 | * @author Andrew Williams
24 | */
25 |
26 | import java.io.File;
27 | import java.io.IOException;
28 | import java.io.InputStream;
29 | import java.net.URL;
30 | import java.util.Enumeration;
31 |
32 | @SuppressWarnings("rawtypes")
33 | @Deprecated
34 | public class DefaultClassRealm implements ClassRealm {
35 | private final ClassRealmAdapter adapter;
36 |
37 | public DefaultClassRealm(ClassWorld world, String id) {
38 | this(world, id, null);
39 | }
40 |
41 | public DefaultClassRealm(ClassWorld world, String id, ClassLoader foreignClassLoader) {
42 | this.adapter = ClassRealmAdapter.getInstance(new org.codehaus.plexus.classworlds.realm.ClassRealm(
43 | ClassWorldReverseAdapter.getInstance(world), id, foreignClassLoader));
44 | }
45 |
46 | public URL[] getConstituents() {
47 | return adapter.getConstituents();
48 | }
49 |
50 | public ClassRealm getParent() {
51 | return adapter.getParentRealm();
52 | }
53 |
54 | public void setParent(ClassRealm parent) {
55 | adapter.setParent(parent);
56 | }
57 |
58 | public String getId() {
59 | return adapter.getId();
60 | }
61 |
62 | public ClassWorld getWorld() {
63 | return adapter.getWorld();
64 | }
65 |
66 | public void importFrom(String realmId, String packageName) throws NoSuchRealmException {
67 | adapter.importFrom(realmId, packageName);
68 | }
69 |
70 | public void addConstituent(URL constituent) {
71 | adapter.addConstituent(constituent);
72 | }
73 |
74 | /**
75 | * Adds a byte[] class definition as a constituent for locating classes.
76 | * Currently uses BytesURLStreamHandler to hold a reference of the byte[] in memory.
77 | * This ensures we have a unifed URL resource model for all constituents.
78 | * The code to cache to disk is commented out - maybe a property to choose which method?
79 | *
80 | * @param constituent class name
81 | * @param b the class definition as a byte[]
82 | * @throws ClassNotFoundException when class couldn't be loaded
83 | */
84 | public void addConstituent(String constituent, byte[] b) throws ClassNotFoundException {
85 | try {
86 | File path, file;
87 | if (constituent.lastIndexOf('.') != -1) {
88 | path = new File("byteclass/"
89 | + constituent
90 | .substring(0, constituent.lastIndexOf('.') + 1)
91 | .replace('.', File.separatorChar));
92 |
93 | file = new File(path, constituent.substring(constituent.lastIndexOf('.') + 1) + ".class");
94 | } else {
95 | path = new File("byteclass/");
96 |
97 | file = new File(path, constituent + ".class");
98 | }
99 |
100 | addConstituent(new URL(null, file.toURI().toURL().toExternalForm(), new BytesURLStreamHandler(b)));
101 | } catch (java.io.IOException e) {
102 | throw new ClassNotFoundException("Couldn't load byte stream.", e);
103 | }
104 | }
105 |
106 | public ClassRealm locateSourceRealm(String classname) {
107 | return adapter.locateSourceRealm(classname);
108 | }
109 |
110 | public ClassLoader getClassLoader() {
111 | return adapter.getClassLoader();
112 | }
113 |
114 | public ClassRealm createChildRealm(String id) throws DuplicateRealmException {
115 | return adapter.createChildRealm(id);
116 | }
117 |
118 | // ----------------------------------------------------------------------
119 | // ClassLoader API
120 | // ----------------------------------------------------------------------
121 |
122 | public Class loadClass(String name) throws ClassNotFoundException {
123 | return adapter.loadClass(name);
124 | }
125 |
126 | public URL getResource(String name) {
127 | return adapter.getResource(name);
128 | }
129 |
130 | public InputStream getResourceAsStream(String name) {
131 | return adapter.getResourceAsStream(name);
132 | }
133 |
134 | public Enumeration findResources(String name) throws IOException {
135 | return adapter.findResources(name);
136 | }
137 |
138 | public void display() {
139 | adapter.display();
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/ClassWorldTest.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | import java.net.URL;
19 | import java.net.URLClassLoader;
20 | import java.util.Enumeration;
21 |
22 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
23 | import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
24 | import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
25 | import org.junit.jupiter.api.AfterEach;
26 | import org.junit.jupiter.api.BeforeEach;
27 | import org.junit.jupiter.api.Test;
28 |
29 | import static org.junit.jupiter.api.Assertions.assertEquals;
30 | import static org.junit.jupiter.api.Assertions.assertNotNull;
31 | import static org.junit.jupiter.api.Assertions.assertSame;
32 | import static org.junit.jupiter.api.Assertions.assertTrue;
33 | import static org.junit.jupiter.api.Assertions.fail;
34 |
35 | class ClassWorldTest extends AbstractClassWorldsTestCase {
36 | private ClassWorld world;
37 |
38 | @BeforeEach
39 | void setUp() {
40 | this.world = new ClassWorld();
41 | }
42 |
43 | @AfterEach
44 | void tearDown() {
45 | this.world = null;
46 | }
47 |
48 | @Test
49 | void empty() {
50 | assertTrue(this.world.getRealms().isEmpty());
51 | }
52 |
53 | @Test
54 | void newRealm() throws Exception {
55 | ClassRealm realm = this.world.newRealm("foo");
56 |
57 | assertNotNull(realm);
58 | }
59 |
60 | @Test
61 | void getRealm() throws Exception {
62 | ClassRealm realm = this.world.newRealm("foo");
63 |
64 | assertSame(realm, this.world.getRealm("foo"));
65 | }
66 |
67 | @Test
68 | void newRealmDuplicate() {
69 | try {
70 | this.world.newRealm("foo");
71 | this.world.newRealm("foo");
72 |
73 | fail("throw DuplicateRealmException");
74 | } catch (DuplicateRealmException e) {
75 | // expected and correct
76 |
77 | assertSame(this.world, e.getWorld());
78 |
79 | assertEquals("foo", e.getId());
80 | }
81 | }
82 |
83 | @Test
84 | void getRealmNoSuch() {
85 | try {
86 | this.world.getRealm("foo");
87 | fail("throw NoSuchRealmException");
88 | } catch (NoSuchRealmException e) {
89 | // expected and correct
90 |
91 | assertSame(this.world, e.getWorld());
92 |
93 | assertEquals("foo", e.getId());
94 | }
95 | }
96 |
97 | @Test
98 | void getRealms() throws Exception {
99 | assertTrue(this.world.getRealms().isEmpty());
100 |
101 | ClassRealm foo = this.world.newRealm("foo");
102 |
103 | assertEquals(1, this.world.getRealms().size());
104 |
105 | assertTrue(this.world.getRealms().contains(foo));
106 |
107 | ClassRealm bar = this.world.newRealm("bar");
108 |
109 | assertEquals(2, this.world.getRealms().size());
110 |
111 | assertTrue(this.world.getRealms().contains(bar));
112 | }
113 |
114 | @Test
115 | void plx334() throws Exception {
116 | ClassLoader loader = new URLClassLoader(new URL[] {getJarUrl("component1-1.0.jar")});
117 | world.newRealm("netbeans", loader);
118 | ClassRealm plexus = world.newRealm("plexus");
119 | plexus.importFrom("netbeans", "META-INF/plexus");
120 | plexus.importFrom("netbeans", "org.codehaus.plexus");
121 | Enumeration e = plexus.getResources("META-INF/plexus/components.xml");
122 | assertNotNull(e);
123 | int resourceCount = 0;
124 | for (Enumeration resources = e; resources.hasMoreElements(); ) {
125 | URL obj = resources.nextElement();
126 | assertTrue(obj.getPath().contains("/component1-1.0.jar!/META-INF/plexus/components.xml"));
127 | resourceCount++;
128 | }
129 | // assertEquals( 2, resourceCount );
130 | // for some reason surefire-plugin 2.3 returned 2 items there:
131 | // for example:
132 | // jar:file:/home/mkleint/.m2/repository/org/codehaus/plexus/plexus-archiver/1.0-alpha-7/plexus-archiver-1.0-alpha-7.jar!/META-INF/plexus/components.xml
133 | // jar:file:/home/mkleint/src/plexus-trunk/plexus-classworlds/src/test-jars/component1-1.0.jar!/META-INF/plexus/components.xml
134 | // However only 1 is correct, which is actually returned by the 2.4 surefire-plugin
135 |
136 | assertEquals(1, resourceCount);
137 | Class> c = plexus.loadClass("org.codehaus.plexus.Component1");
138 | assertNotNull(c);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/site/xdoc/launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | App Launching
7 | bob mcwhirter
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | In order to reduce the number of classloading projects,
18 | Plexus Classworlds replaces forehead
19 | for application launching.
20 |
21 |
22 |
23 | The main problems to solve in application launching include
24 | locating all of application's JARs, configuring the initial
25 | classloaders, and invoking the main entry method.
26 |
27 |
28 |
29 | The launcher facilities
30 | of Classworlds simplify
31 | the process of locating application jars. A common idiom is
32 | to have a script which starts the JVM with only the
33 | plexus-classworlds.jar in the classpath and a system
34 | property to specify the location of a launcher configuration.
35 | Additionally, typically a property specifying the application installation
36 | location is passed on the command-line.
37 |
83 | At least one Classworlds realm must be defined
84 | within the configuration file. The syntax for starting a
85 | realm definition is [realm.name]. All lines
86 | following the realm header are considered directives for
87 | that realm. The realm definition continues either until
88 | another realm is defined or until the end of the file is
89 | reached.
90 |
91 |
92 |
103 |
104 |
105 | Within a realm definition, three directives are available:
106 | load, optionally and import.
107 |
108 |
109 |
110 | The load and optionally
111 | directives specify a class source to be used for loading
112 | classes in the realm: the only difference is that in case of absent source,
113 | load fails but optionally does not.
114 | Any loaded source that contain a star (*) in the file name is
115 | replaced by the list of files that match the filename prefix and suffix.
116 | System properties may be referred to using ${propname} notation.
117 | The load and optionally directives are equivalent to the
118 | addURL(..) method of ClassRealm.
119 |
120 |
121 |
127 |
128 |
129 | The import directive specifies that certain
130 | packages should be imported and loaded by way of another
131 | realm. The import directive is equivalent
132 | to the importFrom(..) method of
133 | ClassRealm.
134 |
135 |
136 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | Classworlds can be used to invoke any existing
151 | application's main() method. Using the standard
152 | entry point does not allow for gaining access to the
153 | ClassWorld of the application, but not all
154 | applications will need it at run-time.
155 |
156 |
157 |
158 | For those applications that do require the ClassWorld
159 | instance, an alternative entry-point method signature can be
160 | provided. Simply add a ClassWorld parameter to
161 | the standard main parameter list.
162 |
163 |
164 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/ClassWorld.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.Closeable;
20 | import java.io.IOException;
21 | import java.util.ArrayList;
22 | import java.util.Collection;
23 | import java.util.Collections;
24 | import java.util.LinkedHashMap;
25 | import java.util.List;
26 | import java.util.Map;
27 | import java.util.function.Predicate;
28 |
29 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
30 | import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
31 | import org.codehaus.plexus.classworlds.realm.FilteredClassRealm;
32 | import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
33 |
34 | /**
35 | * A collection of ClassRealms, indexed by id.
36 | *
37 | * @author bob mcwhirter
38 | */
39 | public class ClassWorld implements Closeable {
40 | private final Map realms;
41 |
42 | private final List listeners = new ArrayList<>();
43 |
44 | public ClassWorld(String realmId, ClassLoader classLoader) {
45 | this();
46 |
47 | try {
48 | newRealm(realmId, classLoader);
49 | } catch (DuplicateRealmException e) {
50 | // Will never happen as we are just creating the world.
51 | }
52 | }
53 |
54 | public ClassWorld() {
55 | this.realms = new LinkedHashMap<>();
56 | }
57 |
58 | public ClassRealm newRealm(String id) throws DuplicateRealmException {
59 | return newRealm(id, getClass().getClassLoader());
60 | }
61 |
62 | public ClassRealm newRealm(String id, ClassLoader classLoader) throws DuplicateRealmException {
63 | return newRealm(id, classLoader, null);
64 | }
65 |
66 | /**
67 | * Adds a class realm with filtering.
68 | * Only resources/classes whose name matches a given predicate are exposed.
69 | * @param id The identifier for this realm, must not be null.
70 | * @param classLoader The base class loader for this realm, may be null to use the bootstrap class
71 | * loader.
72 | * @param filter a predicate to apply to each resource name to determine if it should be loaded through this class loader
73 | * @return the created class realm
74 | * @throws DuplicateRealmException in case a realm with the given id does already exist
75 | * @since 2.7.0
76 | * @see FilteredClassRealm
77 | */
78 | public synchronized ClassRealm newRealm(String id, ClassLoader classLoader, Predicate filter)
79 | throws DuplicateRealmException {
80 | if (realms.containsKey(id)) {
81 | throw new DuplicateRealmException(this, id);
82 | }
83 |
84 | ClassRealm realm;
85 |
86 | if (filter == null) {
87 | realm = new ClassRealm(this, id, classLoader);
88 | } else {
89 | realm = new FilteredClassRealm(filter, this, id, classLoader);
90 | }
91 | realms.put(id, realm);
92 |
93 | for (ClassWorldListener listener : listeners) {
94 | listener.realmCreated(realm);
95 | }
96 |
97 | return realm;
98 | }
99 |
100 | /**
101 | * Closes all contained class realms.
102 | * @since 2.7.0
103 | */
104 | @SuppressWarnings("RedundantThrows")
105 | @Override
106 | public synchronized void close() throws IOException {
107 | realms.values().forEach(this::disposeRealm);
108 | realms.clear();
109 | }
110 |
111 | public synchronized void disposeRealm(String id) throws NoSuchRealmException {
112 | ClassRealm realm = realms.remove(id);
113 |
114 | if (realm != null) {
115 | disposeRealm(realm);
116 | } else {
117 | throw new NoSuchRealmException(this, id);
118 | }
119 | }
120 |
121 | private void disposeRealm(ClassRealm realm) {
122 | try {
123 | realm.close();
124 | } catch (IOException ignore) {
125 | }
126 | for (ClassWorldListener listener : listeners) {
127 | listener.realmDisposed(realm);
128 | }
129 | }
130 |
131 | public synchronized ClassRealm getRealm(String id) throws NoSuchRealmException {
132 | if (realms.containsKey(id)) {
133 | return realms.get(id);
134 | }
135 |
136 | throw new NoSuchRealmException(this, id);
137 | }
138 |
139 | public synchronized Collection getRealms() {
140 | return Collections.unmodifiableList(new ArrayList<>(realms.values()));
141 | }
142 |
143 | // from exports branch
144 | public synchronized ClassRealm getClassRealm(String id) {
145 | if (realms.containsKey(id)) {
146 | return realms.get(id);
147 | }
148 |
149 | return null;
150 | }
151 |
152 | public synchronized void addListener(ClassWorldListener listener) {
153 | // TODO ideally, use object identity, not equals
154 | if (!listeners.contains(listener)) {
155 | listeners.add(listener);
156 | }
157 | }
158 |
159 | public synchronized void removeListener(ClassWorldListener listener) {
160 | listeners.remove(listener);
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/launcher/Configurator.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.launcher;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.io.File;
20 | import java.io.IOException;
21 | import java.io.InputStream;
22 | import java.net.MalformedURLException;
23 | import java.net.URL;
24 | import java.util.ArrayList;
25 | import java.util.HashMap;
26 | import java.util.List;
27 | import java.util.Map;
28 |
29 | import org.codehaus.plexus.classworlds.ClassWorld;
30 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
31 | import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
32 | import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
33 |
34 | /**
35 | * Launcher configurator.
36 | *
37 | * @author bob mcwhirter
38 | * @author Jason van Zyl
39 | */
40 | public class Configurator implements ConfigurationHandler {
41 | /**
42 | * The launcher to configure.
43 | */
44 | private Launcher launcher;
45 |
46 | private ClassWorld world;
47 |
48 | /**
49 | * Processed Realms.
50 | */
51 | private Map configuredRealms;
52 |
53 | /**
54 | * Current Realm.
55 | */
56 | private ClassRealm curRealm;
57 |
58 | private ClassLoader foreignClassLoader = null;
59 |
60 | /**
61 | * Construct.
62 | *
63 | * @param launcher The launcher to configure.
64 | */
65 | public Configurator(Launcher launcher) {
66 | this.launcher = launcher;
67 |
68 | configuredRealms = new HashMap<>();
69 |
70 | if (launcher != null) {
71 | this.foreignClassLoader = launcher.getSystemClassLoader();
72 | }
73 | }
74 |
75 | /**
76 | * Construct.
77 | *
78 | * @param world The classWorld to configure.
79 | */
80 | public Configurator(ClassWorld world) {
81 | setClassWorld(world);
82 | }
83 |
84 | /**
85 | * set world.
86 | * this setter is provided so you can use the same configurator to configure several "worlds"
87 | *
88 | * @param world The classWorld to configure.
89 | */
90 | public void setClassWorld(ClassWorld world) {
91 | this.world = world;
92 |
93 | configuredRealms = new HashMap<>();
94 | }
95 |
96 | /**
97 | * Configure from a file.
98 | *
99 | * @param is The config input stream
100 | * @throws IOException If an error occurs reading the config file.
101 | * @throws MalformedURLException If the config file contains invalid URLs.
102 | * @throws ConfigurationException If the config file is corrupt.
103 | * @throws org.codehaus.plexus.classworlds.realm.DuplicateRealmException If the config file defines two realms with the same id.
104 | * @throws org.codehaus.plexus.classworlds.realm.NoSuchRealmException If the config file defines a main entry point in
105 | * a non-existent realm.
106 | */
107 | public void configure(InputStream is)
108 | throws IOException, ConfigurationException, DuplicateRealmException, NoSuchRealmException {
109 | if (world == null) {
110 | world = new ClassWorld();
111 | }
112 |
113 | curRealm = null;
114 |
115 | foreignClassLoader = null;
116 |
117 | if (this.launcher != null) {
118 | foreignClassLoader = this.launcher.getSystemClassLoader();
119 | }
120 |
121 | ConfigurationParser parser = new ConfigurationParser(this, System.getProperties());
122 |
123 | parser.parse(is);
124 |
125 | // Associate child realms to their parents.
126 | associateRealms();
127 |
128 | if (this.launcher != null) {
129 | this.launcher.setWorld(world);
130 | }
131 | }
132 |
133 | // TODO return this to protected when the legacy wrappers can be removed.
134 | /**
135 | * Associate parent realms with their children.
136 | */
137 | public void associateRealms() {
138 | List sortRealmNames = new ArrayList<>(configuredRealms.keySet());
139 |
140 | // sort by name
141 | sortRealmNames.sort(String::compareTo);
142 |
143 | // So now we have something like the following for defined
144 | // realms:
145 | //
146 | // root
147 | // root.maven
148 | // root.maven.plugin
149 | //
150 | // Now if the name of a realm is a superset of an existing realm
151 | // the we want to make child/parent associations.
152 |
153 | for (String realmName : sortRealmNames) {
154 | int j = realmName.lastIndexOf('.');
155 |
156 | if (j > 0) {
157 | String parentRealmName = realmName.substring(0, j);
158 |
159 | ClassRealm parentRealm = configuredRealms.get(parentRealmName);
160 |
161 | if (parentRealm != null) {
162 | ClassRealm realm = configuredRealms.get(realmName);
163 |
164 | realm.setParentRealm(parentRealm);
165 | }
166 | }
167 | }
168 | }
169 |
170 | public void addImportFrom(String relamName, String importSpec) throws NoSuchRealmException {
171 | curRealm.importFrom(relamName, importSpec);
172 | }
173 |
174 | public void addLoadFile(File file) {
175 | try {
176 | curRealm.addURL(file.toURI().toURL());
177 | } catch (MalformedURLException e) {
178 | // can't really happen... or can it?
179 | }
180 | }
181 |
182 | public void addLoadURL(URL url) {
183 | curRealm.addURL(url);
184 | }
185 |
186 | public void addRealm(String realmName) throws DuplicateRealmException {
187 | curRealm = world.newRealm(realmName, foreignClassLoader);
188 |
189 | // Stash the configured realm for subsequent association processing.
190 | configuredRealms.put(realmName, curRealm);
191 | }
192 |
193 | public void setAppMain(String mainClassName, String mainRealmName) {
194 | if (this.launcher != null) {
195 | this.launcher.setAppMain(mainClassName, mainRealmName);
196 | }
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/src/main/java/org/codehaus/plexus/classworlds/realm/Entry.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.realm;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /**
20 | * Import description entry.
21 | *
22 | * @author bob mcwhirter
23 | */
24 | class Entry implements Comparable {
25 |
26 | final ClassLoader classLoader;
27 |
28 | final String pkgName;
29 |
30 | Entry(ClassLoader realm, String pkgName) {
31 | this.classLoader = realm;
32 |
33 | this.pkgName = pkgName;
34 | }
35 |
36 | // ------------------------------------------------------------
37 | // Instance methods
38 | // ------------------------------------------------------------
39 |
40 | /**
41 | * Retrieve the class loader.
42 | *
43 | * @return The class loader.
44 | */
45 | ClassLoader getClassLoader() {
46 | return this.classLoader;
47 | }
48 |
49 | /**
50 | * Retrieve the package name.
51 | *
52 | * @return The package name.
53 | */
54 | String getPackageName() {
55 | return this.pkgName;
56 | }
57 |
58 | /**
59 | * Determine if the class/resource name matches the package
60 | * described by this entry.
61 | *
62 | * @param name The class or resource name to test, must not be null.
63 | * @return true if this entry matches the
64 | * classname, otherwise false.
65 | */
66 | boolean matches(String name) {
67 | String pkg = getPackageName();
68 |
69 | if (pkg.endsWith(".*")) {
70 | String pkgName;
71 |
72 | if (name.indexOf('/') < 0) {
73 | // a binary class name, e.g. java.lang.Object
74 |
75 | int index = name.lastIndexOf('.');
76 | pkgName = (index < 0) ? "" : name.substring(0, index);
77 | } else {
78 | // a resource name, e.g. java/lang/Object.class
79 |
80 | int index = name.lastIndexOf('/');
81 | pkgName = (index < 0) ? "" : name.substring(0, index).replace('/', '.');
82 | }
83 |
84 | return pkgName.length() == pkg.length() - 2 && pkg.regionMatches(0, pkgName, 0, pkgName.length());
85 | } else if (!pkg.isEmpty()) {
86 | if (name.indexOf('/') < 0) {
87 | // a binary class name, e.g. java.lang.Object
88 |
89 | if (name.startsWith(pkg)) {
90 | if (name.length() == pkg.length()) {
91 | // exact match of class name
92 | return true;
93 | } else if (name.charAt(pkg.length()) == '.') {
94 | // prefix match of package name
95 | return true;
96 | } else //noinspection RedundantIfStatement
97 | if (name.charAt(pkg.length()) == '$') {
98 | // prefix match of enclosing type
99 | return true;
100 | }
101 | }
102 | } else {
103 | // a resource name, e.g. java/lang/Object.class
104 |
105 | if (name.equals(pkg)) {
106 | // exact match of resource name
107 | return true;
108 | }
109 |
110 | pkg = pkg.replace('.', '/');
111 |
112 | if (name.startsWith(pkg) && name.length() > pkg.length()) {
113 | if (name.charAt(pkg.length()) == '/') {
114 | // prefix match of package directory
115 | return true;
116 | } else if (name.charAt(pkg.length()) == '$') {
117 | // prefix match of nested class file
118 | return true;
119 | } else //noinspection RedundantIfStatement
120 | if (name.length() == pkg.length() + 6 && name.endsWith(".class")) {
121 | // exact match of class file
122 | return true;
123 | }
124 | }
125 | }
126 |
127 | return false;
128 | } else {
129 | return true;
130 | }
131 | }
132 |
133 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134 | // java.lang.Comparable
135 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
136 |
137 | /**
138 | * Compare this entry to another for relative ordering.
139 | *
140 | *
141 | * The natural ordering of Entry objects is reverse-alphabetical
142 | * based upon package name.
143 | *
144 | *
145 | * @param that The object to compare.
146 | * @return -1 if this object sorts before that object, 0
147 | * if they are equal, or 1 if this object sorts
148 | * after that object.
149 | */
150 | public int compareTo(Entry that) {
151 | // We are reverse sorting this list, so that
152 | // we get longer matches first:
153 | //
154 | // com.werken.foo.bar
155 | // com.werken.foo
156 | // com.werken
157 |
158 | return -(getPackageName().compareTo(that.getPackageName()));
159 | }
160 |
161 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
162 | // java.lang.Object
163 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
164 |
165 | /**
166 | * Test this entry for equality to another.
167 | *
168 | *
169 | * Consistent with {@link #compareTo}, this method tests
170 | * for equality purely on the package name.
171 | *
172 | *
173 | * @param thatObj The object to compare
174 | * @return true if the two objects are
175 | * semantically equivalent, otherwise false.
176 | */
177 | public boolean equals(Object thatObj) {
178 | Entry that = (Entry) thatObj;
179 |
180 | return getPackageName().equals(that.getPackageName());
181 | }
182 |
183 | /**
184 | *
185 | * Consistent with {@link #equals}, this method creates a hashCode
186 | * based on the packagename.
187 | *
188 | */
189 | public int hashCode() {
190 | return getPackageName().hashCode();
191 | }
192 |
193 | public String toString() {
194 | return "Entry[import " + getPackageName() + " from realm " + getClassLoader() + "]";
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/realm/EntryTest.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.realm;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | import org.codehaus.plexus.classworlds.AbstractClassWorldsTestCase;
19 | import org.codehaus.plexus.classworlds.ClassWorld;
20 | import org.junit.jupiter.api.Test;
21 |
22 | import static org.junit.jupiter.api.Assertions.assertEquals;
23 | import static org.junit.jupiter.api.Assertions.assertFalse;
24 | import static org.junit.jupiter.api.Assertions.assertTrue;
25 |
26 | /**
27 | * @author Ben Walding
28 | */
29 | class EntryTest extends AbstractClassWorldsTestCase {
30 |
31 | @Test
32 | void checkCompareTo() throws Exception {
33 | try (ClassWorld cw = new ClassWorld()) {
34 | ClassRealm r = cw.newRealm("test1");
35 |
36 | Entry entry1 = new Entry(r, "org.test");
37 | Entry entry2 = new Entry(r, "org.test.impl");
38 |
39 | assertTrue(entry1.compareTo(entry2) > 0, "org.test > org.test.impl");
40 | }
41 | }
42 |
43 | /**
44 | * Tests the equality is realm independant
45 | */
46 | @Test
47 | void chckEquals() throws Exception {
48 | try (ClassWorld cw = new ClassWorld()) {
49 | ClassRealm r1 = cw.newRealm("test1");
50 | ClassRealm r2 = cw.newRealm("test2");
51 |
52 | Entry entry1 = new Entry(r1, "org.test");
53 | Entry entry2 = new Entry(r2, "org.test");
54 |
55 | assertEquals(entry1, entry2, "entry1 == entry2");
56 | assertEquals(entry1.hashCode(), entry2.hashCode(), "entry1.hashCode() == entry2.hashCode()");
57 | }
58 | }
59 |
60 | @Test
61 | void matchesClassByPackageImport() throws Exception {
62 | try (ClassWorld cw = new ClassWorld()) {
63 | ClassRealm r = cw.newRealm("test1");
64 |
65 | Entry entry = new Entry(r, "org.test");
66 |
67 | assertTrue(entry.matches("org.test.MyClass"));
68 | assertTrue(entry.matches("org.test.MyClass$NestedClass"));
69 | assertTrue(entry.matches("org.test.MyClassUtils"));
70 | assertTrue(entry.matches("org.test.impl.MyClass"));
71 | assertFalse(entry.matches("org.tests.AnotherClass"));
72 | }
73 | }
74 |
75 | @Test
76 | void matchesClassByClassImport() throws Exception {
77 | try (ClassWorld cw = new ClassWorld()) {
78 | ClassRealm r = cw.newRealm("test1");
79 |
80 | Entry entry = new Entry(r, "org.test.MyClass");
81 |
82 | assertTrue(entry.matches("org.test.MyClass"));
83 | assertTrue(entry.matches("org.test.MyClass$NestedClass"));
84 | assertFalse(entry.matches("org.test.MyClassUtils"));
85 | assertFalse(entry.matches("org.test.AnotherClass"));
86 | }
87 | }
88 |
89 | @Test
90 | void matchesResourceByPackageImport() throws Exception {
91 | try (ClassWorld cw = new ClassWorld()) {
92 | ClassRealm r = cw.newRealm("test1");
93 |
94 | Entry entry = new Entry(r, "org.test");
95 |
96 | assertTrue(entry.matches("org/test/MyClass.class"));
97 | assertTrue(entry.matches("org/test/MyClass$NestedClass.class"));
98 | assertTrue(entry.matches("org/test/MyClasses.properties"));
99 | assertTrue(entry.matches("org/test/impl/MyClass.class"));
100 | assertFalse(entry.matches("org/tests/AnotherClass.class"));
101 | }
102 | }
103 |
104 | @Test
105 | void matchesResourceByClassImport() throws Exception {
106 | try (ClassWorld cw = new ClassWorld()) {
107 | ClassRealm r = cw.newRealm("test1");
108 |
109 | Entry entry = new Entry(r, "org.test.MyClass");
110 |
111 | assertTrue(entry.matches("org/test/MyClass.class"));
112 | assertTrue(entry.matches("org/test/MyClass$NestedClass.class"));
113 | assertFalse(entry.matches("org/test/MyClass.properties"));
114 | assertFalse(entry.matches("org/test/AnotherClass"));
115 | }
116 | }
117 |
118 | @Test
119 | void matchesAllImport() throws Exception {
120 | try (ClassWorld cw = new ClassWorld()) {
121 | ClassRealm r = cw.newRealm("test1");
122 |
123 | Entry entry = new Entry(r, "");
124 |
125 | assertTrue(entry.matches("org.test.MyClass"));
126 | assertTrue(entry.matches("org.test.MyClass$NestedClass"));
127 | assertTrue(entry.matches("org/test/MyClass.class"));
128 | assertTrue(entry.matches("org/test/MyClass.properties"));
129 | }
130 | }
131 |
132 | @Test
133 | void matchesResourceByResourceImport() throws Exception {
134 | try (ClassWorld cw = new ClassWorld()) {
135 | ClassRealm r = cw.newRealm("test1");
136 |
137 | Entry entry1 = new Entry(r, "some.properties");
138 |
139 | assertTrue(entry1.matches("some.properties"));
140 | assertFalse(entry1.matches("other.properties"));
141 |
142 | Entry entry2 = new Entry(r, "org/test/some.properties");
143 |
144 | assertTrue(entry2.matches("org/test/some.properties"));
145 | assertFalse(entry2.matches("org/test/other.properties"));
146 | }
147 | }
148 |
149 | @Test
150 | void matchesClassByExactPackageImport() throws Exception {
151 | try (ClassWorld cw = new ClassWorld()) {
152 | ClassRealm r = cw.newRealm("test1");
153 |
154 | Entry entry = new Entry(r, "org.test.*");
155 |
156 | assertTrue(entry.matches("org.test.MyClass"));
157 | assertTrue(entry.matches("org.test.MyClass$NestedClass"));
158 | assertTrue(entry.matches("org.test.MyClassUtils"));
159 | assertFalse(entry.matches("org.test.impl.MyClass"));
160 | assertFalse(entry.matches("org.tests.AnotherClass"));
161 | }
162 | }
163 |
164 | @Test
165 | void matchesResourceByExactPackageImport() throws Exception {
166 | try (ClassWorld cw = new ClassWorld()) {
167 | ClassRealm r = cw.newRealm("test1");
168 |
169 | Entry entry = new Entry(r, "org.test.*");
170 |
171 | assertTrue(entry.matches("org/test/MyClass.class"));
172 | assertTrue(entry.matches("org/test/MyClass$NestedClass.class"));
173 | assertTrue(entry.matches("org/test/MyClasses.properties"));
174 | assertFalse(entry.matches("org/test/impl/MyClass.class"));
175 | assertFalse(entry.matches("org/tests/AnotherClass.class"));
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 | 4.0.0
20 |
21 |
22 | org.codehaus.plexus
23 | plexus
24 | 24
25 |
26 |
27 | plexus-classworlds
28 | 2.9.1-SNAPSHOT
29 | bundle
30 |
31 | Plexus Classworlds
32 | A class loader framework
33 | https://codehaus-plexus.github.io/plexus-classworlds/
34 | 2002
35 |
36 |
37 | scm:git:git@github.com:codehaus-plexus/plexus-classworlds.git
38 | scm:git:git@github.com:codehaus-plexus/plexus-classworlds.git
39 | master
40 | https://github.com/codehaus-plexus/plexus-classworlds/tree/${project.scm.tag}/
41 |
42 |
43 | github
44 | https://github.com/codehaus-plexus/plexus-classworlds/issues
45 |
46 |
47 |
48 |
49 | github:gh-pages
50 | ${project.scm.developerConnection}
51 |
52 |
53 |
54 |
55 | 2025-04-05T16:29:01Z
56 |
57 |
58 |
59 |
60 | org.junit.jupiter
61 | junit-jupiter-api
62 | test
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | org.apache.maven.plugins
71 | maven-javadoc-plugin
72 |
73 | utf-8
74 | true
75 |
76 |
77 |
78 | org.apache.maven.plugins
79 | maven-scm-publish-plugin
80 |
81 | ${project.reporting.outputDirectory}
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | org.apache.maven.plugins
90 | maven-scm-publish-plugin
91 |
92 |
93 | scm-publish
94 |
95 |
96 | publish-scm
97 |
98 | site-deploy
99 |
100 |
101 |
102 |
103 | org.apache.felix
104 | maven-bundle-plugin
105 | 5.1.9
106 | true
107 |
108 |
109 | <_nouses>true
110 | org.codehaus.classworlds.*;org.codehaus.plexus.classworlds.*
111 |
112 |
113 |
114 |
115 | org.apache.maven.plugins
116 | maven-jar-plugin
117 |
118 |
119 |
120 | org.codehaus.plexus.classworlds.launcher.Launcher
121 |
122 |
123 |
124 |
125 |
126 | org.apache.maven.plugins
127 | maven-surefire-plugin
128 |
129 | true
130 | -ea:org.codehaus.classworlds:org.codehaus.plexus.classworlds
131 | 1
132 |
133 |
134 |
135 | org.apache.maven.plugins
136 | maven-dependency-plugin
137 |
138 |
139 |
140 | copy
141 |
142 | generate-test-resources
143 |
144 |
145 |
146 | org.apache.ant
147 | ant
148 | 1.10.14
149 |
150 |
151 | org.apache.logging.log4j
152 | log4j-api
153 | 2.23.1
154 |
155 |
156 | jakarta.xml.bind
157 | jakarta.xml.bind-api
158 | 4.0.4
159 |
160 |
161 | ${project.build.directory}/test-lib
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 | org.apache.maven.plugins
173 | maven-project-info-reports-plugin
174 |
175 |
176 |
177 | summary
178 | index
179 | dependencies
180 | issue-management
181 | scm
182 |
183 |
184 |
185 |
186 |
187 | org.apache.maven.plugins
188 | maven-javadoc-plugin
189 |
190 |
191 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/realm/DefaultClassRealmTest.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.realm;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | import java.net.URL;
20 | import java.net.URLClassLoader;
21 | import java.util.Collections;
22 | import java.util.concurrent.CountDownLatch;
23 |
24 | import org.codehaus.classworlds.ClassRealmAdapter;
25 | import org.codehaus.plexus.classworlds.AbstractClassWorldsTestCase;
26 | import org.codehaus.plexus.classworlds.ClassWorld;
27 | import org.junit.jupiter.api.Test;
28 |
29 | import static org.junit.jupiter.api.Assertions.assertEquals;
30 | import static org.junit.jupiter.api.Assertions.assertFalse;
31 | import static org.junit.jupiter.api.Assertions.assertNotNull;
32 | import static org.junit.jupiter.api.Assertions.assertNull;
33 | import static org.junit.jupiter.api.Assertions.assertSame;
34 | import static org.junit.jupiter.api.Assertions.assertTrue;
35 | import static org.junit.jupiter.api.Assertions.fail;
36 |
37 | class DefaultClassRealmTest extends AbstractClassWorldsTestCase {
38 | // ----------------------------------------------------------------------
39 | // Class testing
40 | // ----------------------------------------------------------------------
41 |
42 | @Test
43 | void loadClassFromRealm() throws Exception {
44 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
45 |
46 | mainRealm.addURL(getJarUrl("component0-1.0.jar"));
47 |
48 | loadClass(mainRealm, "org.codehaus.plexus.Component0");
49 | }
50 |
51 | @Test
52 | void loadClassFromChildRealmWhereClassIsLocatedInParentRealm() throws Exception {
53 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
54 |
55 | mainRealm.addURL(getJarUrl("component0-1.0.jar"));
56 |
57 | ClassRealm childRealm = mainRealm.createChildRealm("child");
58 |
59 | loadClass(childRealm, "org.codehaus.plexus.Component0");
60 | }
61 |
62 | @Test
63 | void loadClassFromChildRealmWhereClassIsLocatedInGrantParentRealm() throws Exception {
64 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
65 |
66 | mainRealm.addURL(getJarUrl("component0-1.0.jar"));
67 |
68 | ClassRealm childRealm = mainRealm.createChildRealm("child");
69 |
70 | ClassRealm grandchildRealm = childRealm.createChildRealm("grandchild");
71 |
72 | loadClass(grandchildRealm, "org.codehaus.plexus.Component0");
73 | }
74 |
75 | @Test
76 | void loadClassFromChildRealmWhereClassIsLocatedInBothChildRealmAndParentRealm() throws Exception {
77 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "parent", null);
78 |
79 | mainRealm.addURL(getJarUrl("component5-1.0.jar"));
80 |
81 | ClassRealm childRealm = mainRealm.createChildRealm("child");
82 |
83 | childRealm.addURL(getJarUrl("component5-2.0.jar"));
84 |
85 | Class> cls = loadClass(childRealm, "test.Component5");
86 |
87 | assertSame(childRealm, cls.getClassLoader());
88 | assertEquals(1, cls.getMethods().length);
89 | assertEquals("printNew", cls.getMethods()[0].getName());
90 | }
91 |
92 | @Test
93 | void loadNonExistentClass() {
94 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
95 |
96 | mainRealm.addURL(getJarUrl("component0-1.0.jar"));
97 |
98 | try {
99 | mainRealm.loadClass("org.foo.bar.NonExistentClass");
100 |
101 | fail("A ClassNotFoundException should have been thrown!");
102 | } catch (ClassNotFoundException e) {
103 | // expected
104 | }
105 | }
106 |
107 | @Test
108 | void testImport() throws Exception {
109 | try (ClassWorld world = new ClassWorld()) {
110 | ClassRealm r0 = world.newRealm("r0");
111 | ClassRealm r1 = world.newRealm("r1");
112 | r0.addURL(getJarUrl("component0-1.0.jar"));
113 | r1.importFrom("r0", "org.codehaus.plexus");
114 | loadClass(r1, "org.codehaus.plexus.Component0");
115 | }
116 | }
117 |
118 | @Test
119 | void parentImport() throws Exception {
120 | try (ClassWorld world = new ClassWorld()) {
121 |
122 | ClassRealm parent = world.newRealm("parent");
123 |
124 | ClassRealm child = world.newRealm("child");
125 |
126 | parent.addURL(getJarUrl("component0-1.0.jar"));
127 |
128 | child.setParentRealm(parent);
129 |
130 | Class> type = loadClass(child, "org.codehaus.plexus.Component0");
131 |
132 | child.importFromParent("non-existing");
133 |
134 | assertSame(null, loadClassOrNull(child, "org.codehaus.plexus.Component0"));
135 |
136 | child.importFromParent("org.codehaus.plexus");
137 |
138 | assertSame(type, loadClass(child, "org.codehaus.plexus.Component0"));
139 | }
140 | }
141 |
142 | @Test
143 | void loadClassFromBaseClassLoaderBeforeSelf() throws Exception {
144 | try (ClassWorld world = new ClassWorld()) {
145 |
146 | ClassRealm base = world.newRealm("base");
147 |
148 | base.addURL(getJarUrl("a.jar"));
149 |
150 | ClassRealm child = world.newRealm("child", base);
151 |
152 | child.addURL(getJarUrl("a.jar"));
153 |
154 | Class> baseClass = loadClass(base, "a.A");
155 | Class> childClass = loadClass(child, "a.A");
156 |
157 | assertSame(base, baseClass.getClassLoader());
158 | assertSame(base, childClass.getClassLoader());
159 | assertSame(baseClass, childClass);
160 | }
161 | }
162 |
163 | @Test
164 | void loadClassFromRealmWithCircularClassReferences() throws Exception {
165 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
166 |
167 | mainRealm.addURL(getJarUrl("circular-0.1.jar"));
168 |
169 | /*
170 | * This was reported to fail with a ClassCircularityError in IBM JDK 1.5.0-SR2, 1.5.0-SR7 and 1.6.0-SR2. It
171 | * works in IBM JDK 1.5.0-SR10 and 1.6.0-SR6.
172 | */
173 | loadClass(mainRealm, "A$C");
174 | }
175 |
176 | // ----------------------------------------------------------------------
177 | // Resource testing
178 | // ----------------------------------------------------------------------
179 |
180 | @Test
181 | void resource() throws Exception {
182 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
183 |
184 | mainRealm.addURL(getJarUrl("component0-1.0.jar"));
185 |
186 | getResource(mainRealm, "META-INF/plexus/components.xml");
187 | }
188 |
189 | @Test
190 | void malformedResource() throws Exception {
191 | URL jarUrl = getJarUrl("component0-1.0.jar");
192 |
193 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
194 |
195 | mainRealm.addURL(jarUrl);
196 |
197 | try (URLClassLoader officialClassLoader = new URLClassLoader(new URL[] {jarUrl})) {
198 |
199 | String resource = "META-INF/plexus/components.xml";
200 |
201 | assertNotNull(mainRealm.getResource(resource));
202 | assertNotNull(officialClassLoader.getResource(resource));
203 |
204 | /*
205 | * NOTE: Resource names with a leading slash are invalid when passed to a class loader and must not be found!
206 | * One can use a leading slash in Class.getResource() but not in ClassLoader.getResource().
207 | */
208 |
209 | assertSame(null, mainRealm.getResource("/" + resource));
210 | assertSame(null, officialClassLoader.getResource("/" + resource));
211 |
212 | /*
213 | * For backward-compat, legacy class realms have to support leading slashes.
214 | */
215 |
216 | @SuppressWarnings("deprecation")
217 | org.codehaus.classworlds.ClassRealm legacyRealm = ClassRealmAdapter.getInstance(mainRealm);
218 | assertNotNull(legacyRealm.getResource("/" + resource));
219 | assertNotNull(legacyRealm.getResourceAsStream("/" + resource));
220 | assertTrue(legacyRealm.findResources("/" + resource).hasMoreElements());
221 | }
222 | }
223 |
224 | @Test
225 | void findResourceOnlyScansSelf() throws Exception {
226 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
227 |
228 | mainRealm.addURL(getJarUrl("a.jar"));
229 |
230 | ClassRealm childRealm = mainRealm.createChildRealm("child");
231 |
232 | childRealm.addURL(getJarUrl("b.jar"));
233 |
234 | assertNotNull(childRealm.getResource("a.properties"));
235 | assertNotNull(childRealm.getResource("b.properties"));
236 |
237 | assertNull(childRealm.findResource("a.properties"));
238 |
239 | assertNotNull(childRealm.findResource("b.properties"));
240 | }
241 |
242 | @Test
243 | void findResourcesOnlyScansSelf() throws Exception {
244 | ClassRealm mainRealm = new ClassRealm(new ClassWorld(), "main", null);
245 |
246 | mainRealm.addURL(getJarUrl("a.jar"));
247 |
248 | ClassRealm childRealm = mainRealm.createChildRealm("child");
249 |
250 | childRealm.addURL(getJarUrl("b.jar"));
251 |
252 | assertTrue(childRealm.getResources("a.properties").hasMoreElements());
253 | assertTrue(childRealm.getResources("b.properties").hasMoreElements());
254 |
255 | assertFalse(childRealm.findResources("a.properties").hasMoreElements());
256 |
257 | assertTrue(childRealm.findResources("b.properties").hasMoreElements());
258 | }
259 |
260 | /** Should never deadlock. Ever */
261 | @Test
262 | void parallelDeadlockClassRealm() throws Exception {
263 | for (int i = 0; i < 100; i++) {
264 | doOneDeadlockAttempt();
265 | }
266 | }
267 |
268 | private void doOneDeadlockAttempt() throws InterruptedException {
269 | // Deadlock sample graciously ripped from http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html
270 | final ClassRealm cl1 = new ClassRealm(new ClassWorld(), "cl1", null);
271 | final ClassRealm cl2 = new ClassRealm(new ClassWorld(), "cl2", cl1);
272 | cl1.setParentRealm(cl2);
273 | cl1.addURL(getJarUrl("deadlock.jar"));
274 | cl2.addURL(getJarUrl("deadlock.jar"));
275 | final CountDownLatch latch = new CountDownLatch(1);
276 |
277 | Runnable r1 = () -> {
278 | try {
279 | latch.await();
280 | cl1.loadClass("deadlock.A");
281 | } catch (ClassNotFoundException | InterruptedException e) {
282 | throw new RuntimeException(e);
283 | }
284 | };
285 |
286 | Runnable r2 = () -> {
287 | try {
288 | latch.await();
289 | cl1.loadClass("deadlock.C");
290 | } catch (ClassNotFoundException | InterruptedException e) {
291 | throw new RuntimeException(e);
292 | }
293 | };
294 |
295 | Thread thread = new Thread(r1);
296 | thread.start();
297 | Thread thread1 = new Thread(r2);
298 | thread1.start();
299 | latch.countDown();
300 | thread.join();
301 | thread1.join();
302 | }
303 |
304 | // ----------------------------------------------------------------------
305 | //
306 | // ----------------------------------------------------------------------
307 |
308 | private Class> loadClassOrNull(ClassRealm realm, String name) {
309 | try {
310 | return loadClass(realm, name);
311 | } catch (ClassNotFoundException e) {
312 | return null;
313 | }
314 | }
315 |
316 | private Class> loadClass(ClassRealm realm, String name) throws ClassNotFoundException {
317 | Class> cls = realm.loadClass(name);
318 |
319 | /*
320 | * NOTE: Load the class both directly from the realm and indirectly from an (ordinary) child class loader which
321 | * uses the specified class realm for parent delegation. The child class loader itself has no additional class
322 | * path entries but relies entirely on the provided class realm. Hence, the created child class loader should in
323 | * theory be able to load exactly the same classes/resources as the underlying class realm. In practice, it will
324 | * test that class realms properly integrate into the standard Java class loader hierarchy.
325 | */
326 | ClassLoader childLoader = new URLClassLoader(new URL[0], realm);
327 | assertEquals(cls, childLoader.loadClass(name));
328 |
329 | return cls;
330 | }
331 |
332 | private void getResource(ClassRealm realm, String name) throws Exception {
333 | ClassLoader childLoader = new URLClassLoader(new URL[0], realm);
334 | assertNotNull(realm.getResource(name));
335 | assertEquals(realm.getResource(name), childLoader.getResource(name));
336 | assertEquals(Collections.list(realm.getResources(name)), Collections.list(childLoader.getResources(name)));
337 | }
338 | }
339 |
--------------------------------------------------------------------------------
/src/test/java/org/codehaus/plexus/classworlds/launcher/ConfiguratorTest.java:
--------------------------------------------------------------------------------
1 | package org.codehaus.plexus.classworlds.launcher;
2 |
3 | /*
4 | * Copyright 2001-2006 Codehaus Foundation.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | import java.io.File;
19 | import java.io.FileInputStream;
20 | import java.io.FileNotFoundException;
21 | import java.net.URL;
22 | import java.util.Collection;
23 |
24 | import org.codehaus.plexus.classworlds.AbstractClassWorldsTestCase;
25 | import org.codehaus.plexus.classworlds.ClassWorld;
26 | import org.codehaus.plexus.classworlds.TestUtil;
27 | import org.codehaus.plexus.classworlds.realm.ClassRealm;
28 | import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
29 | import org.junit.jupiter.api.AfterEach;
30 | import org.junit.jupiter.api.BeforeEach;
31 | import org.junit.jupiter.api.Test;
32 |
33 | import static org.junit.jupiter.api.Assertions.assertEquals;
34 | import static org.junit.jupiter.api.Assertions.assertNotNull;
35 | import static org.junit.jupiter.api.Assertions.assertNull;
36 | import static org.junit.jupiter.api.Assertions.assertSame;
37 | import static org.junit.jupiter.api.Assertions.assertTrue;
38 | import static org.junit.jupiter.api.Assertions.fail;
39 |
40 | class ConfiguratorTest extends AbstractClassWorldsTestCase {
41 | private Launcher launcher;
42 | private Configurator configurator;
43 |
44 | @BeforeEach
45 | void setUp() {
46 | this.launcher = new Launcher();
47 | this.configurator = new Configurator(this.launcher);
48 | }
49 |
50 | @AfterEach
51 | void tearDown() {
52 | this.launcher = null;
53 | this.configurator = null;
54 | System.getProperties().remove("set.using.existent");
55 | System.getProperties().remove("set.using.default");
56 | System.getProperties().remove("set.using.nonexistent");
57 | System.getProperties().remove("set.using.nonexistent.default");
58 | System.getProperties().remove("set.using.missing");
59 | System.getProperties().remove("set.using.filtered.default");
60 | }
61 |
62 | @Test
63 | void configureNonexistent() throws Exception {
64 | try {
65 | this.configurator.configure(getConfigPath("notfound.conf"));
66 | fail("throw FileNotFoundException");
67 | } catch (FileNotFoundException e) {
68 | // expected and correct
69 | }
70 | }
71 |
72 | @Test
73 | void configureDuplicateMain() throws Exception {
74 | try {
75 | this.configurator.configure(getConfigPath("dupe-main.conf"));
76 | fail("throw ConfigurationException");
77 | } catch (ConfigurationException e) {
78 | // expected and correct
79 | assertTrue(e.getMessage().startsWith("Duplicate main"));
80 | }
81 | }
82 |
83 | @Test
84 | void configureDuplicateRealm() throws Exception {
85 | try {
86 | this.configurator.configure(getConfigPath("dupe-realm.conf"));
87 | fail("throw DuplicateRealmException");
88 | } catch (DuplicateRealmException e) {
89 | // expected and correct
90 | assertEquals("dupe.realm", e.getId());
91 | }
92 | }
93 |
94 | @Test
95 | void configureEarlyImport() throws Exception {
96 | try {
97 | this.configurator.configure(getConfigPath("early-import.conf"));
98 | fail("throw ConfigurationException");
99 | } catch (ConfigurationException e) {
100 | // expected and correct
101 | assertTrue(e.getMessage().startsWith("Unhandled import"));
102 | }
103 | }
104 |
105 | @Test
106 | void configureRealmSyntax() throws Exception {
107 | try {
108 | this.configurator.configure(getConfigPath("realm-syntax.conf"));
109 | fail("throw ConfigurationException");
110 | } catch (ConfigurationException e) {
111 | // expected and correct
112 | assertTrue(e.getMessage().startsWith("Invalid realm"));
113 | }
114 | }
115 |
116 | @Test
117 | void configureValid() throws Exception {
118 | this.configurator.configure(getConfigPath("valid.conf"));
119 |
120 | assertEquals("org.apache.maven.app.App", this.launcher.getMainClassName());
121 |
122 | assertEquals("maven", this.launcher.getMainRealmName());
123 |
124 | ClassWorld world = this.launcher.getWorld();
125 |
126 | Collection realms = world.getRealms();
127 |
128 | assertEquals(4, realms.size());
129 |
130 | assertNotNull(world.getRealm("ant"));
131 | assertNotNull(world.getRealm("maven"));
132 | assertNotNull(world.getRealm("xml"));
133 |
134 | ClassRealm antRealm = world.getRealm("ant");
135 | ClassRealm mavenRealm = world.getRealm("maven");
136 | ClassRealm xmlRealm = world.getRealm("xml");
137 | ClassRealm globRealm = world.getRealm("glob");
138 |
139 | assertSame(null, antRealm.getImportClassLoader("org.apache.tools.Ant"));
140 |
141 | // Ant has dependency to xerces:xercesImpl (test)
142 | assertSame(null, antRealm.getImportClassLoader("org.xml.sax.SAXException"));
143 |
144 | assertSame(xmlRealm, antRealm.getImportClassLoader("jakarta.xml.bind.JAXBException"));
145 |
146 | assertSame(null, mavenRealm.getImportClassLoader("org.apache.maven.app.App"));
147 |
148 | assertSame(xmlRealm, mavenRealm.getImportClassLoader("jakarta.xml.bind.JAXBException"));
149 |
150 | URL[] urls = globRealm.getURLs();
151 |
152 | String basedir = TestUtil.getBasedir();
153 | assertArrayContains(
154 | urls, new File(basedir, "src/test/test-data/nested.jar").toURI().toURL());
155 | assertArrayContains(
156 | urls, new File(basedir, "src/test/test-data/a.jar").toURI().toURL());
157 | assertArrayContains(
158 | urls, new File(basedir, "src/test/test-data/b.jar").toURI().toURL());
159 | assertArrayContains(
160 | urls, new File(basedir, "src/test/test-data/c.jar").toURI().toURL());
161 | }
162 |
163 | @Test
164 | void configureOptionallyNonExistent() throws Exception {
165 | this.configurator.configure(getConfigPath("optionally-nonexistent.conf"));
166 |
167 | assertEquals("org.apache.maven.app.App", this.launcher.getMainClassName());
168 |
169 | assertEquals("opt", this.launcher.getMainRealmName());
170 |
171 | ClassWorld world = this.launcher.getWorld();
172 |
173 | Collection realms = world.getRealms();
174 |
175 | assertEquals(1, realms.size());
176 |
177 | assertNotNull(world.getRealm("opt"));
178 |
179 | ClassRealm optRealm = world.getRealm("opt");
180 |
181 | URL[] urls = optRealm.getURLs();
182 |
183 | assertEquals(0, urls.length, "no urls");
184 | }
185 |
186 | @Test
187 | void configureOptionallyExistent() throws Exception {
188 | this.configurator.configure(getConfigPath("optionally-existent.conf"));
189 |
190 | assertEquals("org.apache.maven.app.App", this.launcher.getMainClassName());
191 |
192 | assertEquals("opt", this.launcher.getMainRealmName());
193 |
194 | ClassWorld world = this.launcher.getWorld();
195 |
196 | Collection realms = world.getRealms();
197 |
198 | assertEquals(1, realms.size());
199 |
200 | assertNotNull(world.getRealm("opt"));
201 |
202 | ClassRealm optRealm = world.getRealm("opt");
203 |
204 | URL[] urls = optRealm.getURLs();
205 |
206 | assertEquals(1, urls.length, "one url");
207 |
208 | assertSame(null, optRealm.getImportClassLoader("jakarta.xml.bind.JAXBException"));
209 | }
210 |
211 | @Test
212 | void configureUnhandled() throws Exception {
213 | try {
214 | this.configurator.configure(getConfigPath("unhandled.conf"));
215 | fail("throw ConfigurationException");
216 | } catch (ConfigurationException e) {
217 | // expected and correct
218 | assertTrue(e.getMessage().startsWith("Unhandled configuration"));
219 | }
220 | }
221 |
222 | @Test
223 | void setUsingExistent() throws Exception {
224 | assertNull(System.getProperty("set.using.existent"));
225 |
226 | this.configurator.configure(getConfigPath("set-using-existent.conf"));
227 |
228 | assertEquals("testSet_Using_Existent", System.getProperty("set.using.existent"));
229 | }
230 |
231 | @Test
232 | void setUsingNonExistent() throws Exception {
233 | assertNull(System.getProperty("set.using.nonexistent"));
234 |
235 | this.configurator.configure(getConfigPath("set-using-nonexistent.conf"));
236 |
237 | assertNull(System.getProperty("set.using.nonexistent"));
238 | }
239 |
240 | @Test
241 | void setUsingNonExistentDefault() throws Exception {
242 | assertNull(System.getProperty("set.using.nonexistent.default"));
243 |
244 | this.configurator.configure(getConfigPath("set-using-nonexistent.conf"));
245 |
246 | assertEquals("testSet_Using_NonExistent_Default", System.getProperty("set.using.nonexistent.default"));
247 | }
248 |
249 | @Test
250 | void setUsingNonExistentOverride() throws Exception {
251 | assertNull(System.getProperty("set.using.default"));
252 | System.setProperty("set.using.default", "testSet_Using_NonExistent_Override");
253 |
254 | this.configurator.configure(getConfigPath("set-using-nonexistent.conf"));
255 |
256 | assertEquals("testSet_Using_NonExistent_Override", System.getProperty("set.using.default"));
257 | }
258 |
259 | @Test
260 | void setUsingExistentOverride() throws Exception {
261 | assertNull(System.getProperty("set.using.existent"));
262 | System.setProperty("set.using.existent", "testSet_Using_Existent_Override");
263 |
264 | this.configurator.configure(getConfigPath("set-using-existent.conf"));
265 |
266 | assertEquals("testSet_Using_Existent_Override", System.getProperty("set.using.existent"));
267 | }
268 |
269 | @Test
270 | void setUsingExistentDefault() throws Exception {
271 | assertNull(System.getProperty("set.using.default"));
272 |
273 | this.configurator.configure(getConfigPath("set-using-existent.conf"));
274 |
275 | assertEquals("testSet_Using_Existent_Default", System.getProperty("set.using.default"));
276 | }
277 |
278 | @Test
279 | void setUsingMissingDefault() throws Exception {
280 | assertNull(System.getProperty("set.using.missing"));
281 |
282 | this.configurator.configure(getConfigPath("set-using-missing.conf"));
283 |
284 | assertEquals("testSet_Using_Missing_Default", System.getProperty("set.using.missing"));
285 | }
286 |
287 | @Test
288 | void setUsingMissingOverride() throws Exception {
289 | assertNull(System.getProperty("set.using.missing"));
290 | System.setProperty("set.using.missing", "testSet_Using_Missing_Override");
291 |
292 | this.configurator.configure(getConfigPath("set-using-missing.conf"));
293 |
294 | assertEquals("testSet_Using_Missing_Override", System.getProperty("set.using.missing"));
295 | }
296 |
297 | @Test
298 | void setUsingFilteredDefault() throws Exception {
299 | assertNull(System.getProperty("set.using.filtered.default"));
300 |
301 | this.configurator.configure(getConfigPath("set-using-missing.conf"));
302 |
303 | assertEquals(System.getProperty("user.home") + "/m2", System.getProperty("set.using.filtered.default"));
304 | }
305 |
306 | @SuppressWarnings("OptionalGetWithoutIsPresent")
307 | @Test
308 | void fromFromFrom() throws Exception {
309 | this.configurator.configure(getConfigPath("valid-from-from-from.conf"));
310 |
311 | assertEquals("com.from.from.from.Main", this.launcher.getMainClassName());
312 |
313 | assertEquals("from", this.launcher.getMainRealmName());
314 |
315 | ClassWorld world = this.launcher.getWorld();
316 |
317 | {
318 | ClassRealm realm = world.getRealm("ant");
319 | Collection importRealms = realm.getImportRealms();
320 | assertEquals(1, importRealms.size());
321 | assertEquals("from", importRealms.stream().findFirst().get().getId());
322 | }
323 | {
324 | ClassRealm realm = world.getRealm("maven");
325 | Collection importRealms = realm.getImportRealms();
326 | assertEquals(1, importRealms.size());
327 | assertEquals("from", importRealms.stream().findFirst().get().getId());
328 | }
329 | {
330 | ClassRealm realm = world.getRealm("glob");
331 | Collection importRealms = realm.getImportRealms();
332 | assertEquals(0, importRealms.size());
333 | }
334 | {
335 | ClassRealm realm = world.getRealm("from");
336 | Collection importRealms = realm.getImportRealms();
337 | assertEquals(0, importRealms.size());
338 | }
339 | }
340 |
341 | private FileInputStream getConfigPath(String name) throws Exception {
342 | return new FileInputStream(new File(new File(TestUtil.getBasedir(), "src/test/test-data"), name));
343 | }
344 |
345 | private void assertArrayContains(URL[] array, URL url) {
346 | for (URL value : array) {
347 | //noinspection UrlHashCode
348 | if (url.equals(value)) {
349 | return;
350 | }
351 | }
352 | fail("URL (" + url + ") not found in array of URLs");
353 | }
354 | }
355 |
--------------------------------------------------------------------------------