Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 307393 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.gemini.web.core/src/main/java/org/eclipse/gemini/web/internal/url/DirTransformer.java (+158 lines)
Line 0 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 SAP AG
3
 *
4
 * All rights reserved. This program and the accompanying materials
5
 * are made available under the terms of the Eclipse Public License v1.0
6
 * and Apache License v2.0 which accompanies this distribution.
7
 * The Eclipse Public License is available at
8
 *   http://www.eclipse.org/legal/epl-v10.html
9
 * and the Apache License v2.0 is available at
10
 *   http://www.opensource.org/licenses/apache2.0.php.
11
 * You may elect to redistribute this code under either of these licenses.
12
 *
13
 * Contributors:
14
 *   Violeta Georgieva - initial contribution
15
 *******************************************************************************/
16
17
package org.eclipse.gemini.web.internal.url;
18
19
import java.io.ByteArrayInputStream;
20
import java.io.ByteArrayOutputStream;
21
import java.io.File;
22
import java.io.FileInputStream;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.io.PrintWriter;
26
import java.net.URL;
27
import java.util.jar.JarFile;
28
29
import org.eclipse.virgo.util.io.IOUtils;
30
import org.eclipse.virgo.util.io.PathReference;
31
32
/**
33
 * Utility class for transforming the files in a directory.
34
 * <p/>
35
 * Files cannot be added, only changed or removed. Actual transformation of files is performed by an implementation of
36
 * the {@link DirTransformerCallback} interface.
37
 */
38
public class DirTransformer {
39
40
    /**
41
     * Callback interface used to transform files in a directory.
42
     * 
43
     * @see DirTransformer
44
     */
45
    public static interface DirTransformerCallback {
46
47
        /**
48
         * Transform the supplied file.
49
         * <p/>
50
         * File content can be read from the supplied {@link InputStream} and transformed contents can be written to the
51
         * supplied {@link File}.
52
         * <p/>
53
         * Implementations <strong>must</strong> return <code>true</code> if the file was transformed or deleted.
54
         * Otherwise, <code>false</code> must be returned. No content should be written when not performing a
55
         * transformation.
56
         * <p/>
57
         * Implementations transforming a file must save the file as <code>toFile</code>. Implementations deleting a
58
         * file must not save the file as <code>toFile</code>.
59
         * 
60
         * @param inputStream the {@link InputStream} that will be transformed
61
         * @param toFile the transformed {@link File}
62
         * @return <code>true</code> if the file was transformed, otherwise <code>false</code>
63
         * @throws IOException if transformation fails
64
         */
65
        boolean transformFile(InputStream inputStream, PathReference toFile) throws IOException;
66
    }
67
68
    private static final String MANIFEST_VERSION_HEADER = "Manifest-Version: 1.0";
69
70
    private final DirTransformerCallback callback;
71
72
    /**
73
     * Creates a new <code>DirTransformer</code> that uses the supplied {@link DirTransformerCallback} for
74
     * transformation.
75
     * 
76
     * @param callback the <code>DirTransformerCallback</code> to use for file transformation.
77
     */
78
    public DirTransformer(DirTransformerCallback callback) {
79
        if (callback == null) {
80
            throw new IllegalArgumentException("Callback must not be null");
81
        }
82
        this.callback = callback;
83
    }
84
85
    /**
86
     * Transforms the directory content in <code>url</code> and writes the results to <code>transformedUrl</code>.
87
     * 
88
     * @param url the {@link URL} of the directory to transform.
89
     * @param transformedUrl the {@link URL} to write the transformed directory to.
90
     * @throws IOException if the directory cannot be transformed.
91
     */
92
    public void transform(URL url, URL transformedUrl) throws IOException {
93
        transform(url, transformedUrl, false);
94
    }
95
96
    /**
97
     * Transforms the directory content in <code>url</code> and writes the results to <code>transformedUrl</code>.
98
     * 
99
     * @param url the {@link URL} of the directory to transform.
100
     * @param transformedUrl the {@link URL} to write the transformed directory to.
101
     * @param ensureManifestIsPresent if <code>true</code> ensures that the transformed directory contains a manifest.
102
     * @throws IOException if the directory cannot be transformed.
103
     */
104
    public void transform(URL url, URL transformedUrl, boolean ensureManifestIsPresent) throws IOException {
105
        PathReference fromDirectory = new PathReference(url.getPath());
106
        PathReference toDirectory = new PathReference(transformedUrl.getPath());
107
        transformDir(fromDirectory, toDirectory);
108
109
        PathReference manifest = fromDirectory.newChild(JarFile.MANIFEST_NAME);
110
        if (ensureManifestIsPresent && !manifest.exists()) {
111
            InputStream defaultManifestStream = getDefaultManifestStream();
112
            PathReference toFile = toDirectory.newChild(JarFile.MANIFEST_NAME);
113
            toFile.getParent().createDirectory();
114
            try {
115
                this.callback.transformFile(defaultManifestStream, toFile);
116
            } finally {
117
                IOUtils.closeQuietly(defaultManifestStream);
118
            }
119
        }
120
    }
121
122
    private void transformDir(PathReference fromDirectory, PathReference toDirectory) throws IOException {
123
        File[] fileList = fromDirectory.toFile().listFiles();
124
        PathReference fromFile = null;
125
        for (int i = 0; fileList != null && i < fileList.length; i++) {
126
            fromFile = new PathReference(fileList[i]);
127
            PathReference toFile = toDirectory.newChild(fromFile.getName());
128
            if (!fromFile.isDirectory()) {
129
                transformFile(fromFile, toFile);
130
            } else {
131
                transformDir(fromFile, toFile);
132
            }
133
        }
134
    }
135
136
    private void transformFile(PathReference fromFile, PathReference toFile) throws IOException {
137
        FileInputStream fis = new FileInputStream(fromFile.toFile());
138
        boolean transformed = false;
139
        try {
140
            transformed = this.callback.transformFile(fis, toFile);
141
        } finally {
142
            IOUtils.closeQuietly(fis);
143
        }
144
        if (!transformed) {
145
            toFile.getParent().createDirectory();
146
            fromFile.copy(toFile);
147
        }
148
    }
149
150
    private InputStream getDefaultManifestStream() {
151
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
152
        PrintWriter writer = new PrintWriter(baos);
153
        writer.println(MANIFEST_VERSION_HEADER);
154
        writer.println();
155
        writer.close();
156
        return new ByteArrayInputStream(baos.toByteArray());
157
    }
158
}
(-)a/org.eclipse.gemini.web.core/src/main/java/org/eclipse/gemini/web/internal/url/DirTransformingURLConnection.java (+117 lines)
Line 0 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 SAP AG
3
 *
4
 * All rights reserved. This program and the accompanying materials
5
 * are made available under the terms of the Eclipse Public License v1.0
6
 * and Apache License v2.0 which accompanies this distribution.
7
 * The Eclipse Public License is available at
8
 *   http://www.eclipse.org/legal/epl-v10.html
9
 * and the Apache License v2.0 is available at
10
 *   http://www.opensource.org/licenses/apache2.0.php.
11
 * You may elect to redistribute this code under either of these licenses.
12
 *
13
 * Contributors:
14
 *   Violeta Georgieva - initial contribution
15
 *******************************************************************************/
16
17
package org.eclipse.gemini.web.internal.url;
18
19
import java.io.IOException;
20
import java.io.InputStream;
21
import java.net.MalformedURLException;
22
import java.net.URISyntaxException;
23
import java.net.URL;
24
import java.net.URLConnection;
25
26
import org.eclipse.virgo.util.io.PathReference;
27
28
/**
29
 * Implementation of {@link URLConnection} that transforms directory files as they are read.
30
 * <p/>
31
 * A {@link URL} is used to source the real connection for the directory data, and a {@link DirTransformer} is used to
32
 * customize the exact transformations being performed.
33
 * 
34
 * @see DirTransformer
35
 */
36
public class DirTransformingURLConnection extends URLConnection {
37
38
    private static final String TEMP_DIR = "file:temp/";
39
40
    private final DirTransformer transformer;
41
42
    private final boolean ensureManifestIsPresent;
43
44
    private URL transformedURL;
45
46
    /**
47
     * Creates a new <code>DirTransformingURLConnection</code> that will provide content from the directory identified
48
     * by <code>url</code> transformed by <code>transformer</code>.
49
     * 
50
     * @param url the {@link URL} of the directory.
51
     * @param transformer the <code>DirTransformer</code> to apply as content is being read.
52
     * @throws MalformedURLException the exception is thrown in case the new URL, where is the transformed data, cannot
53
     *         be created.
54
     * @throws URISyntaxException
55
     */
56
    public DirTransformingURLConnection(URL url, DirTransformer transformer) throws MalformedURLException {
57
        this(url, transformer, false);
58
    }
59
60
    /**
61
     * Creates a new <code>DirTransformingURLConnection</code> that will provide content from the directory identified
62
     * by <code>url</code> transformed by <code>transformer</code> and that will optionally ensure that a manifest is
63
     * provided, creating one if necessary.
64
     * 
65
     * @param url the {@link URL} of the directory.
66
     * @param transformer the <code>DirTransformer</code> to apply as content is being read.
67
     * @param ensureManifestIsPresent <code>true</code> if the presence of a MANIFEST.MF should be ensured.
68
     * @throws MalformedURLException the exception is thrown in case the new URL, where is the transformed data, cannot
69
     *         be created.
70
     * @throws URISyntaxException
71
     */
72
    public DirTransformingURLConnection(URL url, DirTransformer transformer, boolean ensureManifestIsPresent) throws MalformedURLException {
73
        super(url);
74
        this.transformer = transformer;
75
        this.ensureManifestIsPresent = ensureManifestIsPresent;
76
77
        this.transformedURL = new URL(TEMP_DIR + getPath());
78
        PathReference transformedDir = new PathReference(this.transformedURL.getPath());
79
        transformedDir.delete(true);
80
    }
81
82
    @Override
83
    public void connect() throws IOException {
84
    }
85
86
    /**
87
     * Transform the URL before returning the input stream.
88
     */
89
    @Override
90
    public InputStream getInputStream() throws IOException {
91
        this.transformer.transform(this.url, this.transformedURL, this.ensureManifestIsPresent);
92
        return this.transformedURL.openStream();
93
    }
94
95
    private String getPath() {
96
        String path = this.url.getPath();
97
        int index = path.lastIndexOf('/');
98
        if (index > -1) {
99
            path = path.substring(index + 1);
100
        }
101
102
        return path;
103
    }
104
105
    /**
106
     * Returns transformed URL instead of the original one.
107
     */
108
    @Override
109
    public URL getURL() {
110
        return this.transformedURL;
111
    }
112
113
    void setTransformedURL(URL transformedURL) {
114
        this.transformedURL = transformedURL;
115
    }
116
117
}
(-)a/org.eclipse.gemini.web.core/src/main/java/org/eclipse/gemini/web/internal/url/WebBundleUrlStreamHandlerService.java (-18 / +64 lines)
Lines 16-24 Link Here
16
16
17
package org.eclipse.gemini.web.internal.url;
17
package org.eclipse.gemini.web.internal.url;
18
18
19
import java.io.File;
20
import java.io.FileOutputStream;
19
import java.io.IOException;
21
import java.io.IOException;
20
import java.io.InputStream;
22
import java.io.InputStream;
21
import java.io.InputStreamReader;
23
import java.io.InputStreamReader;
24
import java.io.OutputStream;
22
import java.net.URL;
25
import java.net.URL;
23
import java.net.URLConnection;
26
import java.net.URLConnection;
24
import java.util.Dictionary;
27
import java.util.Dictionary;
Lines 36-44 import org.osgi.service.url.URLStreamHandlerService; Link Here
36
import org.eclipse.gemini.web.core.InstallationOptions;
39
import org.eclipse.gemini.web.core.InstallationOptions;
37
import org.eclipse.gemini.web.core.WebBundleManifestTransformer;
40
import org.eclipse.gemini.web.core.WebBundleManifestTransformer;
38
import org.eclipse.gemini.web.internal.WebContainerUtils;
41
import org.eclipse.gemini.web.internal.WebContainerUtils;
42
import org.eclipse.gemini.web.internal.url.DirTransformer.DirTransformerCallback;
43
import org.eclipse.virgo.util.io.IOUtils;
39
import org.eclipse.virgo.util.io.JarTransformer;
44
import org.eclipse.virgo.util.io.JarTransformer;
40
import org.eclipse.virgo.util.io.JarTransformingURLConnection;
45
import org.eclipse.virgo.util.io.JarTransformingURLConnection;
41
import org.eclipse.virgo.util.io.JarTransformer.JarTransformerCallback;
46
import org.eclipse.virgo.util.io.JarTransformer.JarTransformerCallback;
47
import org.eclipse.virgo.util.io.PathReference;
42
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
48
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
43
import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory;
49
import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory;
44
50
Lines 50-56 import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory; Link Here
50
 * @see WebBundleManifestTransformer
56
 * @see WebBundleManifestTransformer
51
 */
57
 */
52
public final class WebBundleUrlStreamHandlerService extends AbstractURLStreamHandlerService {
58
public final class WebBundleUrlStreamHandlerService extends AbstractURLStreamHandlerService {
53
59
    private static final String FILE_PROTOCOL = "file";
60
    
54
    private final WebBundleManifestTransformer transformer;
61
    private final WebBundleManifestTransformer transformer;
55
62
56
    public WebBundleUrlStreamHandlerService(WebBundleManifestTransformer transformer) {
63
    public WebBundleUrlStreamHandlerService(WebBundleManifestTransformer transformer) {
Lines 61-73 public final class WebBundleUrlStreamHandlerService extends AbstractURLStreamHan Link Here
61
    public URLConnection openConnection(URL u) throws IOException {
68
    public URLConnection openConnection(URL u) throws IOException {
62
        WebBundleUrl url = new WebBundleUrl(u);
69
        WebBundleUrl url = new WebBundleUrl(u);
63
        URL actualUrl = new URL(url.getLocation());
70
        URL actualUrl = new URL(url.getLocation());
64
71
        
65
        JarTransformer jarTransformer = new JarTransformer(new Callback(actualUrl, url, this.transformer));
72
        if (FILE_PROTOCOL.equals(actualUrl.getProtocol()) && new File(actualUrl.getPath()).isDirectory()) {
66
        return new JarTransformingURLConnection(actualUrl, jarTransformer, true);
73
            DirTransformer dirTransformer = new DirTransformer(new Callback(actualUrl, url, this.transformer));
74
            return new DirTransformingURLConnection(actualUrl, dirTransformer, true);
75
        } else {
76
            JarTransformer jarTransformer = new JarTransformer(new Callback(actualUrl, url, this.transformer));
77
            return new JarTransformingURLConnection(actualUrl, jarTransformer, true);
78
        }
67
    }
79
    }
68
80
69
    private static final class Callback implements JarTransformerCallback {
81
    private static final class Callback implements JarTransformerCallback, DirTransformerCallback {
70
82
        private static final String META_INF = "META-INF";
83
        private static final String MANIFEST_MF = "MANIFEST.MF";
84
        
71
        private final WebBundleManifestTransformer transformer;
85
        private final WebBundleManifestTransformer transformer;
72
86
73
        private final URL sourceURL;
87
        private final URL sourceURL;
Lines 83-99 public final class WebBundleUrlStreamHandlerService extends AbstractURLStreamHan Link Here
83
        public boolean transformEntry(String entryName, InputStream is, JarOutputStream jos) throws IOException {
97
        public boolean transformEntry(String entryName, InputStream is, JarOutputStream jos) throws IOException {
84
            if (JarFile.MANIFEST_NAME.equals(entryName)) {
98
            if (JarFile.MANIFEST_NAME.equals(entryName)) {
85
                jos.putNextEntry(new ZipEntry(entryName));
99
                jos.putNextEntry(new ZipEntry(entryName));
86
                InputStreamReader reader = new InputStreamReader(is);
100
                transformManifest(is, jos);
87
                BundleManifest manifest = BundleManifestFactory.createBundleManifest(reader);
88
                InstallationOptions options = new InstallationOptions(this.webBundleUrl.getOptions());
89
                if (manifest.getHeader(WebContainerUtils.HEADER_SPRINGSOURCE_DEFAULT_WAB_HEADERS) != null) {
90
                    options.setDefaultWABHeaders(true);
91
                }
92
93
                boolean webBundle = WebContainerUtils.isWebApplicationBundle(manifest);
94
                this.transformer.transform(manifest, sourceURL, options, webBundle);
95
96
                toManifest(manifest.toDictionary()).write(jos);
97
                jos.closeEntry();
101
                jos.closeEntry();
98
                return true;
102
                return true;
99
            }
103
            }
Lines 102-111 public final class WebBundleUrlStreamHandlerService extends AbstractURLStreamHan Link Here
102
            return isSignatureFile(entryName);
106
            return isSignatureFile(entryName);
103
        }
107
        }
104
108
109
        private void transformManifest(InputStream inputStream, OutputStream outputStream) throws IOException {
110
            InputStreamReader reader = new InputStreamReader(inputStream);
111
            BundleManifest manifest = BundleManifestFactory.createBundleManifest(reader);
112
            InstallationOptions options = new InstallationOptions(this.webBundleUrl.getOptions());
113
            if (manifest.getHeader(WebContainerUtils.HEADER_SPRINGSOURCE_DEFAULT_WAB_HEADERS) != null) {
114
                options.setDefaultWABHeaders(true);
115
            }
116
117
            boolean webBundle = WebContainerUtils.isWebApplicationBundle(manifest);
118
            this.transformer.transform(manifest, sourceURL, options, webBundle);
119
120
            toManifest(manifest.toDictionary()).write(outputStream);
121
        }
122
        
105
        private boolean isSignatureFile(String entryName) {
123
        private boolean isSignatureFile(String entryName) {
106
            String[] entryNameComponents = entryName.split("/");
124
            String[] entryNameComponents = entryName.split("/");
107
            if (entryNameComponents.length == 2) {
125
            if (entryNameComponents.length == 2) {
108
                if ("META-INF".equals(entryNameComponents[0])) {
126
                if (META_INF.equals(entryNameComponents[0])) {
109
                    String entryFileName = entryNameComponents[1];
127
                    String entryFileName = entryNameComponents[1];
110
                    if (entryFileName.endsWith(".SF") || entryFileName.endsWith(".DSA") || entryFileName.endsWith(".RSA")) {
128
                    if (entryFileName.endsWith(".SF") || entryFileName.endsWith(".DSA") || entryFileName.endsWith(".RSA")) {
111
                        return true;
129
                        return true;
Lines 129-134 public final class WebBundleUrlStreamHandlerService extends AbstractURLStreamHan Link Here
129
            return manifest;
147
            return manifest;
130
        }
148
        }
131
149
150
        public boolean transformFile(InputStream inputStream, PathReference toFile) throws IOException {
151
            if (MANIFEST_MF.equals(toFile.getName()) && META_INF.equals(toFile.getParent().getName())) {
152
                toFile.getParent().createDirectory();
153
                OutputStream outputStream = null;
154
                try {
155
                    outputStream = new FileOutputStream(toFile.toFile());
156
                    transformManifest(inputStream, outputStream);
157
                } finally {
158
                    IOUtils.closeQuietly(outputStream);
159
                }
160
                return true;
161
            }
162
163
            // Delete signature files. Should be generalized into another
164
            // transformer type.
165
            return isSignatureFile(toFile);
166
        }
167
168
        private boolean isSignatureFile(PathReference file) {
169
            if (META_INF.equals(file.getParent().getName())) {
170
                String fileName = file.getName();
171
                if (fileName.endsWith(".SF") || fileName.endsWith(".DSA") || fileName.endsWith(".RSA")) {
172
                    return true;
173
                }
174
            }
175
            return false;
176
        }
177
132
    }
178
    }
133
179
134
}
180
}
(-)a/org.eclipse.gemini.web.core/src/test/java/org/eclipse/gemini/web/internal/url/DirTransformerTest.java (+198 lines)
Line 0 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 SAP AG
3
 *
4
 * All rights reserved. This program and the accompanying materials
5
 * are made available under the terms of the Eclipse Public License v1.0
6
 * and Apache License v2.0 which accompanies this distribution.
7
 * The Eclipse Public License is available at
8
 *   http://www.eclipse.org/legal/epl-v10.html
9
 * and the Apache License v2.0 is available at
10
 *   http://www.opensource.org/licenses/apache2.0.php.
11
 * You may elect to redistribute this code under either of these licenses.
12
 *
13
 * Contributors:
14
 *   Violeta Georgieva - initial contribution
15
 *******************************************************************************/
16
17
package org.eclipse.gemini.web.internal.url;
18
19
import static org.junit.Assert.assertEquals;
20
import static org.junit.Assert.assertTrue;
21
22
import java.io.File;
23
import java.io.FileInputStream;
24
import java.io.FileOutputStream;
25
import java.io.IOException;
26
import java.io.InputStream;
27
import java.io.OutputStream;
28
import java.io.PrintWriter;
29
import java.net.URL;
30
import java.util.ArrayList;
31
import java.util.List;
32
import java.util.jar.Attributes;
33
import java.util.jar.JarFile;
34
import java.util.jar.Manifest;
35
36
import org.eclipse.gemini.web.internal.url.DirTransformer.DirTransformerCallback;
37
import org.eclipse.virgo.util.io.IOUtils;
38
import org.eclipse.virgo.util.io.PathReference;
39
import org.junit.Test;
40
41
public class DirTransformerTest {
42
43
    private static final String WEB_INF = "WEB-INF";
44
45
    private static final String META_INF = "META-INF";
46
47
    private static final String WEB_XML = "web.xml";
48
49
    private static final String MANIFEST_MF = "MANIFEST.MF";
50
51
    private static final String HEADER_1 = "Manifest-Version: 1.0";
52
53
    private static final String HEADER_2 = "Class-Path: ";
54
55
    private static final String HEADER_3 = "Custom-Header: test";
56
57
    private static final String SOURCE_URL = "file:target/test-classes/web-app-dir";
58
59
    private static final String TARGET_URL = "file:target/test-classes/temp/web-app-dir";
60
61
    @Test
62
    public void testTransformManifestAdded() throws Exception {
63
        URL directory = new URL(SOURCE_URL);
64
        URL tempDirectory = new URL(TARGET_URL);
65
66
        // Create content
67
        PathReference webAppDir = new PathReference(directory.getPath());
68
        PathReference webXml = webAppDir.newChild(WEB_INF + File.separator + WEB_XML);
69
        webXml.createFile();
70
        PathReference manifest = webAppDir.newChild(JarFile.MANIFEST_NAME);
71
72
        final List<PathReference> transformedFiles = new ArrayList<PathReference>();
73
        DirTransformer transformer = new DirTransformer(new DirTransformerCallback() {
74
75
            public boolean transformFile(InputStream inputStream, PathReference toFile) throws IOException {
76
                transformedFiles.add(toFile);
77
                return false;
78
            }
79
        });
80
81
        PathReference tempWebAppDir = new PathReference(tempDirectory.getPath());
82
        transformer.transform(directory, tempDirectory, false);
83
        assertEquals(1, transformedFiles.size());
84
        assertTrue(!manifest.exists());
85
        assertTrue(!transformedFiles.contains(manifest));
86
        assertTrue(tempWebAppDir.delete(true));
87
        transformedFiles.clear();
88
89
        transformer.transform(directory, tempDirectory, true);
90
        assertEquals(2, transformedFiles.size());
91
        assertTrue(!manifest.exists());
92
        assertTrue(transformedFiles.contains(tempWebAppDir.newChild(JarFile.MANIFEST_NAME)));
93
94
        assertTrue(tempWebAppDir.delete(true));
95
        assertTrue(webAppDir.delete(true));
96
    }
97
98
    @Test
99
    public void testTransformManifestChanged() throws Exception {
100
        URL directory = new URL(SOURCE_URL);
101
        URL tempDirectory = new URL(TARGET_URL);
102
103
        // Create content
104
        PathReference webAppDir = new PathReference(directory.getPath());
105
        PathReference manifest = webAppDir.newChild(JarFile.MANIFEST_NAME);
106
        manifest.getParent().createDirectory();
107
        createManifest(manifest.toFile(), HEADER_1, HEADER_2);
108
109
        DirTransformer transformer = new DirTransformer(new DirTransformerCallback() {
110
111
            public boolean transformFile(InputStream inputStream, PathReference toFile) throws IOException {
112
                if (MANIFEST_MF.equals(toFile.getName()) && META_INF.equals(toFile.getParent().getName())) {
113
                    toFile.getParent().createDirectory();
114
                    createManifest(toFile.toFile(), HEADER_3);
115
                    return true;
116
                } else {
117
                    return false;
118
                }
119
            }
120
        });
121
122
        transformer.transform(directory, tempDirectory);
123
        PathReference tempWebAppDir = new PathReference(tempDirectory.getPath());
124
        checkManifest(tempWebAppDir.newChild(JarFile.MANIFEST_NAME).toFile());
125
126
        assertTrue(tempWebAppDir.delete(true));
127
        assertTrue(webAppDir.delete(true));
128
    }
129
130
    @Test
131
    public void testTransformNoChanges() throws Exception {
132
        URL directory = new URL(SOURCE_URL);
133
        URL tempDirectory = new URL(TARGET_URL);
134
135
        // Create content
136
        PathReference webAppDir = new PathReference(directory.getPath());
137
        PathReference webXml = webAppDir.newChild(WEB_INF + File.separator + WEB_XML);
138
        webXml.createFile();
139
140
        DirTransformer transformer;
141
        try {
142
            transformer = new DirTransformer(null);
143
        } catch (Exception e) {
144
            assertTrue("Callback must not be null".equals(e.getMessage()));
145
        }
146
147
        transformer = new DirTransformer(new DirTransformerCallback() {
148
149
            public boolean transformFile(InputStream inputStream, PathReference toFile) throws IOException {
150
                return false;
151
            }
152
        });
153
154
        transformer.transform(directory, tempDirectory);
155
        PathReference tempWebAppDir = new PathReference(tempDirectory.getPath());
156
        assertDirsSame(webAppDir.toFile(), tempWebAppDir.toFile());
157
158
        assertTrue(tempWebAppDir.delete(true));
159
        assertTrue(webAppDir.delete(true));
160
    }
161
162
    private void assertDirsSame(File source, File destination) throws IOException {
163
        assertEquals(source.getName(), destination.getName());
164
        assertEquals(source.length(), destination.length());
165
166
        File[] sourceFiles = source.listFiles();
167
        File[] destinationFiles = destination.listFiles();
168
        assertEquals(sourceFiles.length, destinationFiles.length);
169
170
        for (int i = 0; i < sourceFiles.length; i++) {
171
            File sourceFile = sourceFiles[i];
172
            File destinationFile = destinationFiles[i];
173
            assertEquals(sourceFile.getName(), destinationFile.getName());
174
            assertEquals(sourceFile.length(), destinationFile.length());
175
        }
176
    }
177
178
    private void checkManifest(File manifestFile) throws IOException {
179
        InputStream is = new FileInputStream(manifestFile);
180
        Manifest manifest = new Manifest(is);
181
        Attributes attr = manifest.getMainAttributes();
182
        String value = attr.getValue("Custom-Header");
183
        assertEquals("test", value);
184
        assertEquals(1, attr.size());
185
        IOUtils.closeQuietly(is);
186
    }
187
188
    private void createManifest(File manifest, String... headers) throws IOException {
189
        OutputStream outputStream = new FileOutputStream(manifest);
190
        PrintWriter writer = new PrintWriter(manifest);
191
        for (String header : headers) {
192
            writer.println(header);
193
        }
194
        writer.println();
195
        writer.close();
196
        IOUtils.closeQuietly(outputStream);
197
    }
198
}
(-)a/org.eclipse.gemini.web.core/src/test/java/org/eclipse/gemini/web/internal/url/DirTransformingURLConnectionTest.java (+76 lines)
Line 0 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 SAP AG
3
 *
4
 * All rights reserved. This program and the accompanying materials
5
 * are made available under the terms of the Eclipse Public License v1.0
6
 * and Apache License v2.0 which accompanies this distribution.
7
 * The Eclipse Public License is available at
8
 *   http://www.eclipse.org/legal/epl-v10.html
9
 * and the Apache License v2.0 is available at
10
 *   http://www.opensource.org/licenses/apache2.0.php.
11
 * You may elect to redistribute this code under either of these licenses.
12
 *
13
 * Contributors:
14
 *   Violeta Georgieva - initial contribution
15
 *******************************************************************************/
16
17
package org.eclipse.gemini.web.internal.url;
18
19
import static org.junit.Assert.assertNotNull;
20
import static org.junit.Assert.assertTrue;
21
22
import java.io.File;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.net.URL;
26
import java.util.ArrayList;
27
import java.util.List;
28
29
import org.eclipse.gemini.web.internal.url.DirTransformer.DirTransformerCallback;
30
import org.eclipse.virgo.util.io.PathReference;
31
import org.junit.Test;
32
33
public class DirTransformingURLConnectionTest {
34
35
    private static final String WEB_INF = "WEB-INF";
36
37
    private static final String WEB_XML = "web.xml";
38
39
    private static final String SOURCE_URL = "file:target/test-classes/web-app-dir";
40
41
    private static final String TARGET_URL = "file:target/test-classes/temp/web-app-dir";
42
43
    @Test
44
    public void testGetURL() throws Exception {
45
        URL directory = new URL(SOURCE_URL);
46
        URL tempDirectory = new URL(TARGET_URL);
47
48
        // Create content
49
        PathReference webAppDir = new PathReference(directory.getPath());
50
        PathReference webXml = webAppDir.newChild(WEB_INF + File.separator + WEB_XML);
51
        webXml.createFile();
52
53
        final List<PathReference> files = new ArrayList<PathReference>();
54
        DirTransformer transformer = new DirTransformer(new DirTransformerCallback() {
55
56
            public boolean transformFile(InputStream inputStream, PathReference toFile) throws IOException {
57
                files.add(toFile);
58
                return false;
59
            }
60
        });
61
62
        DirTransformingURLConnection connection = new DirTransformingURLConnection(directory, transformer);
63
        connection.setTransformedURL(tempDirectory);
64
        InputStream is = connection.getInputStream();
65
        assertNotNull(is);
66
        URL url = connection.getURL();
67
        assertTrue(tempDirectory.equals(url));
68
69
        PathReference tempWebAppDir = new PathReference(tempDirectory.getPath());
70
        assertTrue(tempWebAppDir.newChild(WEB_INF + File.separator + WEB_XML).exists());
71
        assertTrue(files.size() == 1);
72
73
        assertTrue(tempWebAppDir.delete(true));
74
        assertTrue(webAppDir.delete(true));
75
    }
76
}
(-)a/org.eclipse.gemini.web.core/src/test/java/org/eclipse/gemini/web/internal/url/WebBundleUrlStreamHandlerServiceTests.java (+104 lines)
Lines 17-24 Link Here
17
package org.eclipse.gemini.web.internal.url;
17
package org.eclipse.gemini.web.internal.url;
18
18
19
import static org.junit.Assert.assertNotNull;
19
import static org.junit.Assert.assertNotNull;
20
import static org.junit.Assert.assertTrue;
21
import static org.junit.Assert.assertEquals;
20
22
23
import java.io.File;
24
import java.io.FileInputStream;
25
import java.io.FileOutputStream;
21
import java.io.InputStream;
26
import java.io.InputStream;
27
import java.io.OutputStream;
28
import java.io.PrintWriter;
22
import java.net.MalformedURLException;
29
import java.net.MalformedURLException;
23
import java.net.URL;
30
import java.net.URL;
24
import java.net.URLConnection;
31
import java.net.URLConnection;
Lines 27-38 import java.util.Map; Link Here
27
import java.util.Set;
34
import java.util.Set;
28
import java.util.Map.Entry;
35
import java.util.Map.Entry;
29
import java.util.jar.Attributes;
36
import java.util.jar.Attributes;
37
import java.util.jar.JarFile;
30
import java.util.jar.JarInputStream;
38
import java.util.jar.JarInputStream;
31
import java.util.jar.Manifest;
39
import java.util.jar.Manifest;
32
40
33
import org.eclipse.gemini.web.internal.url.SpecificationWebBundleManifestTransformer;
41
import org.eclipse.gemini.web.internal.url.SpecificationWebBundleManifestTransformer;
34
import org.eclipse.gemini.web.internal.url.WebBundleUrl;
42
import org.eclipse.gemini.web.internal.url.WebBundleUrl;
35
import org.eclipse.gemini.web.internal.url.WebBundleUrlStreamHandlerService;
43
import org.eclipse.gemini.web.internal.url.WebBundleUrlStreamHandlerService;
44
import org.eclipse.virgo.util.io.FileSystemUtils;
45
import org.eclipse.virgo.util.io.IOUtils;
46
import org.eclipse.virgo.util.io.PathReference;
36
import org.junit.Test;
47
import org.junit.Test;
37
48
38
public class WebBundleUrlStreamHandlerServiceTests {
49
public class WebBundleUrlStreamHandlerServiceTests {
Lines 56-61 public class WebBundleUrlStreamHandlerServiceTests { Link Here
56
        }
67
        }
57
    }
68
    }
58
    
69
    
70
    @Test
71
    public void testOpenDirConnection() throws Exception {
72
        URL directory = new URL("file:target/test-classes/web-app-dir");
73
        URL tempDirectory = new URL("file:target/test-classes/temp/web-app-dir");
74
75
        // Create content
76
        PathReference webAppDir = new PathReference(directory.getPath());
77
        PathReference webXml = webAppDir.newChild("WEB-INF" + File.separator + "web.xml");
78
        webXml.createFile();
79
80
        PathReference signatureFile = webAppDir.newChild("META-INF" + File.separator + "signature.SF");
81
        signatureFile.createFile();
82
83
        // There is no Manifest in the directory
84
        // Expectation: Manifest will have Web-ContextPath header
85
        WebBundleUrl url = new TestWarUrl("file:target/test-classes/web-app-dir?Web-ContextPath=/test", null);
86
        DirTransformingURLConnection connection = (DirTransformingURLConnection) url.toURL().openConnection();
87
        assertNotNull(connection);
88
        connection.setTransformedURL(tempDirectory);
89
        checkContent(connection, "/test", webXml.toFile());
90
        assertTrue(FileSystemUtils.deleteRecursively(tempDirectory.getPath()));
91
92
        // Create content
93
        PathReference manifest = webAppDir.newChild(JarFile.MANIFEST_NAME);
94
        manifest.createFile();
95
        createManifest(manifest.toFile(), "Manifest-Version: 1.0", "Class-Path: ");
96
97
        // There is Manifest in the directory with basic headers
98
        // Expectation: Manifest will have Web-ContextPath header
99
        url = new TestWarUrl("file:target/test-classes/web-app-dir?Web-ContextPath=/test1", null);
100
        connection = (DirTransformingURLConnection) url.toURL().openConnection();
101
        assertNotNull(connection);
102
        connection.setTransformedURL(tempDirectory);
103
        checkContent(connection, "/test1", webXml.toFile());
104
        assertTrue(FileSystemUtils.deleteRecursively(tempDirectory.getPath()));
105
106
        // Create content
107
        createManifest(manifest.toFile(), "Manifest-Version: 1.0", "Class-Path: ", "Web-ContextPath: /test2");
108
109
        // There is Manifest in the directory with basic headers +
110
        // Web-ContextPath header
111
        // Expectation: Manifest will have Web-ContextPath header
112
        url = new TestWarUrl("file:target/test-classes/web-app-dir", null);
113
        connection = (DirTransformingURLConnection) url.toURL().openConnection();
114
        assertNotNull(connection);
115
        connection.setTransformedURL(tempDirectory);
116
        checkContent(connection, "/test2", webXml.toFile());
117
        assertTrue(FileSystemUtils.deleteRecursively(tempDirectory.getPath()));
118
119
        assertTrue(FileSystemUtils.deleteRecursively(directory.getPath()));
120
    }
121
122
    private void checkContent(URLConnection connection, String contextPath, File webXml) throws Exception {
123
        InputStream inputStream = connection.getInputStream();
124
        assertNotNull(inputStream);
125
126
        File webAppDir = new File(connection.getURL().getPath());
127
        // Check Manifest
128
        InputStream is = new FileInputStream(new File(webAppDir, JarFile.MANIFEST_NAME));
129
        Manifest manifest = new Manifest(is);
130
131
        if (manifest != null) {
132
            Attributes mainAttributes = manifest.getMainAttributes();
133
            Set<Entry<Object, Object>> entrySet = mainAttributes.entrySet();
134
            for (Entry<Object, Object> entry : entrySet) {
135
                System.out.println(entry.getKey() + ": " + entry.getValue());
136
                if ("Web-ContextPath".equals(entry.getKey().toString())) {
137
                    assertTrue(contextPath.equals(entry.getValue().toString()));
138
                }
139
            }
140
        }
141
142
        IOUtils.closeQuietly(is);
143
144
        // Check web.xml
145
        assertEquals(webXml.length(), new File(webAppDir, "WEB-INF" + File.separator + "web.xml").length());
146
147
        // Check signature file
148
        File signatureFile = new File(webAppDir, "META-INF" + File.separator + "signature.SF");
149
        assertTrue(!signatureFile.exists());
150
    }
151
152
    private void createManifest(File manifest, String... headers) throws Exception {
153
        OutputStream os = new FileOutputStream(manifest);
154
        PrintWriter writer = new PrintWriter(os);
155
        for (String header : headers) {
156
            writer.println(header);
157
        }
158
        writer.println();
159
        writer.close();
160
        IOUtils.closeQuietly(os);
161
    }
162
    
59
    private static class TestWarUrl extends WebBundleUrl {
163
    private static class TestWarUrl extends WebBundleUrl {
60
164
61
        public TestWarUrl(String location, Map<String, String> options) throws MalformedURLException {
165
        public TestWarUrl(String location, Map<String, String> options) throws MalformedURLException {
(-)a/org.eclipse.gemini.web.test/src/test/java/org/eclipse/gemini/web/test/tomcat/TomcatServletContainerTests.java (-6 / +29 lines)
Lines 3-14 Link Here
3
 *
3
 *
4
 * All rights reserved. This program and the accompanying materials
4
 * All rights reserved. This program and the accompanying materials
5
 * are made available under the terms of the Eclipse Public License v1.0
5
 * are made available under the terms of the Eclipse Public License v1.0
6
 * and Apache License v2.0 which accompanies this distribution. 
6
 * and Apache License v2.0 which accompanies this distribution.
7
 * The Eclipse Public License is available at
7
 * The Eclipse Public License is available at
8
 *   http://www.eclipse.org/legal/epl-v10.html
8
 *   http://www.eclipse.org/legal/epl-v10.html
9
 * and the Apache License v2.0 is available at 
9
 * and the Apache License v2.0 is available at
10
 *   http://www.opensource.org/licenses/apache2.0.php.
10
 *   http://www.opensource.org/licenses/apache2.0.php.
11
 * You may elect to redistribute this code under either of these licenses.  
11
 * You may elect to redistribute this code under either of these licenses.
12
 *
12
 *
13
 * Contributors:
13
 * Contributors:
14
 *   VMware Inc. - initial contribution
14
 *   VMware Inc. - initial contribution
Lines 50-55 import org.eclipse.gemini.web.core.spi.ServletContainer; Link Here
50
import org.eclipse.gemini.web.core.spi.WebApplicationHandle;
50
import org.eclipse.gemini.web.core.spi.WebApplicationHandle;
51
import org.eclipse.virgo.test.framework.OsgiTestRunner;
51
import org.eclipse.virgo.test.framework.OsgiTestRunner;
52
import org.eclipse.virgo.test.framework.TestFrameworkUtils;
52
import org.eclipse.virgo.test.framework.TestFrameworkUtils;
53
import org.eclipse.virgo.util.io.FileSystemUtils;
53
import org.eclipse.virgo.util.io.IOUtils;
54
import org.eclipse.virgo.util.io.IOUtils;
54
import org.eclipse.virgo.util.io.PathReference;
55
import org.eclipse.virgo.util.io.PathReference;
55
import org.eclipse.virgo.util.io.ZipUtils;
56
import org.eclipse.virgo.util.io.ZipUtils;
Lines 84-94 public class TomcatServletContainerTests { Link Here
84
85
85
    private static final String LOCATION_WAR_WITH_CONTEXT_XML_CROSS_CONTEXT = LOCATION_PREFIX
86
    private static final String LOCATION_WAR_WITH_CONTEXT_XML_CROSS_CONTEXT = LOCATION_PREFIX
86
        + "../org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-cross-context.war?Web-ContextPath=/war-with-context-xml-cross-context";
87
        + "../org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-cross-context.war?Web-ContextPath=/war-with-context-xml-cross-context";
87
    
88
88
    private BundleContext bundleContext;
89
    private BundleContext bundleContext;
89
90
90
    private ServletContainer container;
91
    private ServletContainer container;
91
    
92
92
    @BeforeClass
93
    @BeforeClass
93
    public static void beforeClass() throws Exception {
94
    public static void beforeClass() throws Exception {
94
        System.setProperty("org.eclipse.gemini.web.tomcat.config.path", "target/config/tomcat-server.xml");
95
        System.setProperty("org.eclipse.gemini.web.tomcat.config.path", "target/config/tomcat-server.xml");
Lines 396-408 public class TomcatServletContainerTests { Link Here
396
397
397
            this.container.stopWebApplication(handle2);
398
            this.container.stopWebApplication(handle2);
398
            bundle2.uninstall();
399
            bundle2.uninstall();
399
            
400
400
            defaultContextXml.delete();
401
            defaultContextXml.delete();
401
            defaultHostContextXml.delete();
402
            defaultHostContextXml.delete();
402
            tomcatServerXml.delete();
403
            tomcatServerXml.delete();
403
        }
404
        }
404
    }
405
    }
405
406
407
    @Test
408
    public void testInstallWebAppDir() throws Exception {
409
        //Create web app dir
410
        File webAppDir = new File("target/test-classes/simple-web-app-dir");
411
        File indexHtml = new File(webAppDir, "index.html");
412
        createFileWithContent(indexHtml, "Hello World!");
413
414
        Bundle bundle = this.bundleContext.installBundle(LOCATION_PREFIX + webAppDir.getAbsolutePath() + "?Web-ContextPath=/simple-web-app-dir");
415
        bundle.start();
416
417
        WebApplicationHandle handle = this.container.createWebApplication("/simple-web-app-dir", bundle);
418
        this.container.startWebApplication(handle);
419
        try {
420
            validateURL("http://localhost:8080/simple-web-app-dir/index.html");
421
        } finally {
422
            this.container.stopWebApplication(handle);
423
            bundle.uninstall();
424
            FileSystemUtils.deleteRecursively(webAppDir);
425
            FileSystemUtils.deleteRecursively(new File("temp"));
426
        }
427
    }
428
406
    private void createFileWithContent(File file, String content) throws Exception {
429
    private void createFileWithContent(File file, String content) throws Exception {
407
        file.getParentFile().mkdirs();
430
        file.getParentFile().mkdirs();
408
        FileWriter fWriter = null;
431
        FileWriter fWriter = null;

Return to bug 307393