();
36 |
37 | /**
38 | * Constructor
39 | */
40 | public URIResourceFactoryImpl(SchemeURIResourceFactory... factories)
41 | {
42 | for(SchemeURIResourceFactory factory : factories)
43 | {
44 | _factories.put(factory.getScheme(), factory);
45 | }
46 | }
47 |
48 | /**
49 | * Based on the URI returns the right resource
50 | *
51 | * @param uri
52 | * @return the resource
53 | * @throws UnsupportedURIException if the uri is not supported by this factory
54 | */
55 | @Override
56 | public Resource createResource(URI uri) throws UnsupportedURIException
57 | {
58 | if(uri.getScheme() == null)
59 | return FileResource.createFromRoot(new File(uri.getPath()));
60 |
61 | SchemeURIResourceFactory factory = _factories.get(uri.getScheme());
62 | if(factory == null)
63 | throw new UnsupportedURIException("unsupported scheme " + uri.getScheme());
64 |
65 | return factory.createResource(uri, this);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/UnsupportedURIException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource;
18 |
19 | /**
20 | * @author ypujante@linkedin.com
21 | *
22 | */
23 | public class UnsupportedURIException extends Exception
24 | {
25 | private static final long serialVersionUID = 1L;
26 |
27 | public UnsupportedURIException()
28 | {
29 | }
30 |
31 | public UnsupportedURIException(Throwable cause)
32 | {
33 | super(cause);
34 | }
35 |
36 | public UnsupportedURIException(String message)
37 | {
38 | super(message);
39 | }
40 |
41 | public UnsupportedURIException(String message, Throwable cause)
42 | {
43 | super(message, cause);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/FileResourceProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.slf4j.Logger;
20 | import org.slf4j.LoggerFactory;
21 | import org.linkedin.util.io.resource.FileResource;
22 | import org.linkedin.util.io.resource.ResourceFilter;
23 |
24 | import java.io.File;
25 | import java.io.IOException;
26 |
27 | /**
28 | * @author ypujante@linkedin.com
29 | *
30 | */
31 | public class FileResourceProvider extends AbstractResourceProvider
32 | {
33 | public static final String MODULE = FileResourceProvider.class.getName();
34 | public static final Logger log = LoggerFactory.getLogger(MODULE);
35 |
36 | private final File _root;
37 |
38 | /**
39 | * Constructor
40 | */
41 | public FileResourceProvider(File root) throws IOException
42 | {
43 | _root = root.getCanonicalFile();
44 | }
45 |
46 | /**
47 | * Builds a resource given a path. Only subclasses know how to do that.
48 | *
49 | * @param path the path to the new resource (always starts with /)
50 | * @return the resource
51 | */
52 | @Override
53 | public InternalResource doBuildResource(String path)
54 | {
55 | return new FileResource(this, path, new File(_root, path));
56 | }
57 |
58 |
59 | /**
60 | * Creates a new resource provider given the new path.
61 | *
62 | * @param rootPath
63 | * @return the new resource provider
64 | */
65 | @Override
66 | public InternalResourceProvider doCreateResourceProvider(String rootPath)
67 | {
68 | try
69 | {
70 | return new FileResourceProvider(new File(_root, rootPath));
71 | }
72 | catch(IOException e)
73 | {
74 | throw new RuntimeException(e);
75 | }
76 | }
77 |
78 | /**
79 | * If the path denotes a directory, then it will return all resources that are contained in the
80 | * directory.
81 | *
82 | * @param path the path to the resource
83 | * @param filter the filter to include only some resources in the result
84 | * @return true
if it was a directory, false
otherwise
85 | */
86 | @Override
87 | public boolean doList(String path, ResourceFilter filter)
88 | {
89 | File file = null;
90 | try
91 | {
92 | file = new File(_root, path).getCanonicalFile();
93 | }
94 | catch(IOException e)
95 | {
96 | if(log.isDebugEnabled())
97 | log.debug("exception (ignored) while converting canonical file " + new File(_root, path), e);
98 |
99 | return false;
100 | }
101 |
102 | if(!file.isDirectory())
103 | return false;
104 |
105 | File[] files = file.listFiles();
106 |
107 | for(File f : files)
108 | {
109 | filter.accept(new FileResource(this, path + f.getName(), f));
110 | }
111 |
112 | return true;
113 | }
114 |
115 | @Override
116 | public boolean equals(Object o)
117 | {
118 | if(this == o) return true;
119 | if(o == null || getClass() != o.getClass()) return false;
120 |
121 | FileResourceProvider that = (FileResourceProvider) o;
122 |
123 | if(!_root.equals(that._root)) return false;
124 |
125 | return true;
126 | }
127 |
128 | @Override
129 | public int hashCode()
130 | {
131 | return _root.hashCode();
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/FileURIResourceFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.FileResource;
20 | import org.linkedin.util.io.resource.Resource;
21 | import org.linkedin.util.io.resource.URIResourceFactory;
22 |
23 | import java.io.File;
24 | import java.net.URI;
25 |
26 | /**
27 | * @author ypujante@linkedin.com
28 | *
29 | */
30 | public class FileURIResourceFactory extends SchemeURIResourceFactory
31 | {
32 | /**
33 | * Constructor
34 | */
35 | public FileURIResourceFactory()
36 | {
37 | }
38 |
39 | /**
40 | * @return the protocol that this factory handles
41 | */
42 | @Override
43 | public String getScheme()
44 | {
45 | return "file";
46 | }
47 |
48 |
49 | /**
50 | * Method that needs to be implemented by children..
51 | *
52 | * @param uri
53 | * @param parent the parent resource factory
54 | * @return the resource
55 | */
56 | @Override
57 | protected Resource doCreateResource(URI uri, URIResourceFactory parent)
58 | {
59 | return FileResource.create(new File("/"), uri.getPath());
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/FilteredResourceProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.FilteredResource;
20 | import org.linkedin.util.io.resource.Resource;
21 | import org.linkedin.util.io.resource.ResourceFilter;
22 |
23 | /**
24 | * @author ypujante@linkedin.com
25 | *
26 | */
27 | public class FilteredResourceProvider extends AbstractResourceProvider
28 | {
29 | private final InternalResourceProvider _resourceProvider;
30 |
31 | /**
32 | * Constructor
33 | */
34 | public FilteredResourceProvider(InternalResourceProvider resourceProvider)
35 | {
36 | _resourceProvider = resourceProvider;
37 | }
38 |
39 | /**
40 | * Constructor
41 | */
42 | public FilteredResourceProvider(Resource resource)
43 | {
44 | this((InternalResourceProvider) ((InternalResource) resource).getResourceProvider());
45 | }
46 |
47 | /**
48 | * @return the filtered resource provider
49 | */
50 | public InternalResourceProvider getFilteredResourceProvider()
51 | {
52 | return _resourceProvider;
53 | }
54 |
55 | /**
56 | * Builds a resource given a path. Only subclasses know how to do that.
57 | *
58 | * @param path the path to the new resource (always starts with /)
59 | * @return the resource
60 | */
61 | @Override
62 | public InternalResource doBuildResource(String path)
63 | {
64 | return doBuildResource(_resourceProvider.doBuildResource(path));
65 | }
66 |
67 | /**
68 | * Creates a new resource provider given the new path.
69 | *
70 | * @param rootPath
71 | * @return the new resource provider
72 | */
73 | @Override
74 | public InternalResourceProvider doCreateResourceProvider(String rootPath)
75 | {
76 | return doCreateResourceProvider(_resourceProvider.doCreateResourceProvider(rootPath));
77 | }
78 |
79 | /**
80 | * This method will be implemented by subclasses to create the right kind of resource provider
81 | *
82 | * @param resourceProvider
83 | * @return the resource provider
84 | */
85 | protected InternalResourceProvider doCreateResourceProvider(InternalResourceProvider resourceProvider)
86 | {
87 | return new FilteredResourceProvider(resourceProvider);
88 | }
89 |
90 | /**
91 | * If the path denotes a directory, then it will return all resources that are contained in the
92 | * directory.
93 | *
94 | * @param path the path to the resource (it already ends with /)
95 | * @param filter the filter to include only some resources in the result
96 | * @return true
if it was a directory, false
otherwise
97 | */
98 | @Override
99 | public boolean doList(String path, final ResourceFilter filter)
100 | {
101 | ResourceFilter newFilter = new ResourceFilter()
102 | {
103 | @Override
104 | public boolean accept(Resource resource)
105 | {
106 | return filter.accept(doBuildResource(resource));
107 | }
108 | };
109 |
110 | return _resourceProvider.doList(path, newFilter);
111 | }
112 |
113 | /**
114 | * This method will be implemented by subclasses to create the right kind of resource.
115 | *
116 | * @param filteredResource
117 | * @return the resource
118 | */
119 | protected InternalResource doBuildResource(Resource filteredResource)
120 | {
121 | return new FilteredResource(this, filteredResource.getPath(), filteredResource);
122 | }
123 |
124 | @Override
125 | public boolean equals(Object o)
126 | {
127 | if(this == o) return true;
128 | if(o == null || getClass() != o.getClass()) return false;
129 |
130 | FilteredResourceProvider that = (FilteredResourceProvider) o;
131 |
132 | if(!_resourceProvider.equals(that._resourceProvider)) return false;
133 |
134 | return true;
135 | }
136 |
137 | @Override
138 | public int hashCode()
139 | {
140 | return _resourceProvider.hashCode();
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/InternalResource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.Resource;
20 |
21 | /**
22 | * All resources need to implement this internal interface.
23 | *
24 | * @author ypujante@linkedin.com
25 | *
26 | */
27 | public interface InternalResource extends Resource
28 | {
29 | /**
30 | * @return the resource provider that created this resource
31 | */
32 | ResourceProvider getResourceProvider();
33 | }
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/InternalResourceProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.ResourceFilter;
20 |
21 | import java.io.IOException;
22 |
23 | /**
24 | * All resource providers need to implement this internal interface.
25 | *
26 | * @author ypujante@linkedin.com
27 | *
28 | */
29 | public interface InternalResourceProvider extends ResourceProvider
30 | {
31 | /**
32 | * @param resource
33 | * @return the parent of a resource
34 | */
35 | InternalResource getParentResource(InternalResource resource);
36 |
37 | /**
38 | * @param resource
39 | * @param relativePath the relative path
40 | * @return a resource relative to the resource
41 | */
42 | InternalResource createRelative(InternalResource resource, String relativePath);
43 |
44 | /**
45 | * Returns a new resource with the root resource set to this resource.
46 | *
47 | * @return the new resource
48 | */
49 | InternalResource chroot(InternalResource resource);
50 |
51 | /**
52 | * If this resource denotes a directory, then it will return all resources that are contained
53 | * in the directory.
54 | *
55 | * @param filter the filter to include only some resources in the result
56 | * @return all the resources contained in the directory or null
if not a directory
57 | * @throws IOException if there is an error accessing the resource
58 | */
59 | InternalResource[] list(InternalResource resource, ResourceFilter filter) throws IOException;
60 |
61 | /**
62 | * @return the root resource
63 | */
64 | InternalResource getRootResource();
65 |
66 | /**
67 | * Builds a resource given a path. Only subclasses know how to do that.
68 | *
69 | * @param path the path to the new resource (always starts with /)
70 | * @return the resource
71 | */
72 | InternalResource doBuildResource(String path);
73 |
74 | /**
75 | * If the path denotes a directory, then it will return all resources that are contained in
76 | * the directory.
77 | *
78 | * @param path the path to the resource (it already ends with /)
79 | * @param filter the filter to include only some resources in the result
80 | * @return true
if it was a directory, false
otherwise
81 | */
82 | boolean doList(String path, ResourceFilter filter);
83 |
84 | /**
85 | * Creates a new resource provider given the new path.
86 | *
87 | * @param rootPath
88 | * @return the new resource provider
89 | */
90 | InternalResourceProvider doCreateResourceProvider(String rootPath);
91 | }
92 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/JarURIResourceFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.JarResource;
20 | import org.linkedin.util.io.resource.Resource;
21 | import org.linkedin.util.io.resource.URIResourceFactory;
22 |
23 | import java.io.IOException;
24 | import java.net.URI;
25 | import java.net.URISyntaxException;
26 |
27 | /**
28 | * @author ypujante@linkedin.com
29 | *
30 | */
31 | public class JarURIResourceFactory extends SchemeURIResourceFactory
32 | {
33 | /**
34 | * Constructor
35 | */
36 | public JarURIResourceFactory()
37 | {
38 | }
39 |
40 | /**
41 | * @return the protocol that this factory handles
42 | */
43 | @Override
44 | public String getScheme()
45 | {
46 | return "jar";
47 | }
48 |
49 | /**
50 | * Method that needs to be implemented by children..
51 | *
52 | * @param uri
53 | * @param parent the parent resource factory
54 | * @return the resource
55 | * @throws IOException if there is a problem creating the resource
56 | */
57 | @Override
58 | protected Resource doCreateResource(URI uri, URIResourceFactory parent)
59 | {
60 | try
61 | {
62 | return JarResource.create(uri, parent);
63 | }
64 | catch(URISyntaxException e)
65 | {
66 | throw new IllegalArgumentException(uri.toString(), e);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/LeafResource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.Resource;
20 | import org.linkedin.util.io.resource.ResourceInfo;
21 |
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 | import java.io.File;
25 | import java.net.URI;
26 |
27 | /**
28 | * Subset of the interface {@link Resource} when we have a leaf (meaning a file). Note that this
29 | * api does not have any 'navigation' features (like createRelative
or
30 | * getParentResource
).
31 | *
32 | * @author ypujante@linkedin.com
33 | *
34 | */
35 | public interface LeafResource
36 | {
37 | /**
38 | * @return true
if the resource exists.
39 | */
40 | boolean exists();
41 |
42 | /**
43 | * Returns a File
handle for this resource.
44 | *
45 | * @throws IOException if the resource cannot be resolved as a File
handle, i.e.
46 | * it is not available on the file system (or it cannot be made available).
47 | */
48 | File getFile() throws IOException;
49 |
50 | /**
51 | * Efficiently returns all information about the resource.
52 | *
53 | * @return information about this resource.
54 | * @throws IOException if cannot get information
55 | */
56 | ResourceInfo getInfo() throws IOException;
57 |
58 | /**
59 | * Shortcut to getInfo().getLastModified()
with the same meaning as the
60 | * File.lastModified
api: returns 0L
if the resource does not
61 | * exist or if an IO error occurs.
62 | *
63 | * @return the last modified date of this resource.
64 | */
65 | long lastModified();
66 |
67 | /**
68 | * Returns true
if this resource was modified since the time provided. A trivial
69 | * implementation is return lastModified() > time
, but various implementations
70 | * can provide better alternatives. If the resource does not exsit then it returns
71 | * false
.
72 | *
73 | * @param time the time to check against
74 | * @return a boolean
75 | */
76 | boolean isModifiedSince(long time);
77 |
78 | /**
79 | * Shortcut to getInfo().getContentLength()
with the same meaning as the
80 | * File.length()
api: returns 0L
if the resource does not
81 | * exist or if an IO error occurs.
82 | *
83 | * @return the length in bytes of the resource.
84 | */
85 | long length();
86 |
87 | /**
88 | * @return a uri representation of the resource
89 | */
90 | URI toURI();
91 |
92 | /**
93 | * @return the filename portion of this resource. If it is a directory, returns the name of the
94 | * directory.
95 | */
96 | String getFilename();
97 |
98 | /**
99 | * @return the path to the resource (within the context of the resource provider)
100 | */
101 | String getPath();
102 |
103 | /**
104 | * Important note: the caller of this method is responsible for properly closing the
105 | * input stream!
106 | *
107 | * @return an input stream to the resource.
108 | * @throws IOException if cannot get an input stream
109 | */
110 | InputStream getInputStream() throws IOException;
111 | }
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/NullResourceProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.PathUtils;
20 | import org.linkedin.util.io.resource.NullResource;
21 | import org.linkedin.util.io.resource.ResourceFilter;
22 |
23 | /**
24 | * Implements the null pattern for resource (does not exist)
25 | * @author ypujante@linkedin.com
26 | */
27 | public class NullResourceProvider extends PathBasedResourceProvider
28 | {
29 |
30 |
31 | /**
32 | * Constructor
33 | */
34 | public NullResourceProvider()
35 | {
36 | this("/");
37 | }
38 |
39 | /**
40 | * Constructor
41 | */
42 | public NullResourceProvider(String root)
43 | {
44 | super(normalizePath(root));
45 | }
46 |
47 | /**
48 | * Builds a resource given a path. Only subclasses know how to do that.
49 | *
50 | * @param path the path to the new resource (always starts with /)
51 | * @return the resource
52 | */
53 | @Override
54 | public InternalResource doBuildResource(String path)
55 | {
56 | return new NullResource(this, normalizePath(path), normalizePath(getFullPath(path)));
57 | }
58 |
59 | /**
60 | * The path never represents a directory => should not end with /
61 | */
62 | private static String normalizePath(String path)
63 | {
64 | path = PathUtils.removeTrailingSlash(path);
65 | path = PathUtils.addLeadingSlash(path);
66 | return path;
67 | }
68 |
69 | /**
70 | * Creates a new resource provider given the new path.
71 | *
72 | * @param rootPath
73 | * @return the new resource provider
74 | */
75 | @Override
76 | public InternalResourceProvider doCreateResourceProvider(String rootPath)
77 | {
78 | return new NullResourceProvider(getFullPath(rootPath));
79 | }
80 |
81 | /**
82 | * If the path denotes a directory, then it will return all resources that are contained in the
83 | * directory.
84 | *
85 | * @param path the path to the resource
86 | * @param filter the filter to include only some resources in the result
87 | * @return true
if it was a directory, false
otherwise
88 | */
89 | @Override
90 | public boolean doList(String path, ResourceFilter filter)
91 | {
92 | return false;
93 | }
94 | }
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/PathBasedResourceProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.PathUtils;
20 |
21 | import java.net.URI;
22 |
23 | /**
24 | * Case were there is a root path...
25 | *
26 | * @author ypujante@linkedin.com
27 | *
28 | */
29 | public abstract class PathBasedResourceProvider extends AbstractResourceProvider
30 | {
31 | private final String _root;
32 |
33 | /**
34 | * Constructor
35 | */
36 | public PathBasedResourceProvider(String root)
37 | {
38 | root = URI.create(root).normalize().getPath();
39 | _root = PathUtils.addLeadingSlash(root);
40 | }
41 |
42 | protected String getFullPath(String path)
43 | {
44 | return PathUtils.addPaths(_root, path);
45 | }
46 |
47 | protected String getRelativePath(String fullPath)
48 | {
49 | return PathUtils.addLeadingSlash(fullPath.substring(_root.length()));
50 | }
51 |
52 | public String getRoot()
53 | {
54 | return _root;
55 | }
56 |
57 | @Override
58 | public boolean equals(Object o)
59 | {
60 | if(this == o) return true;
61 | if(o == null || getClass() != o.getClass()) return false;
62 |
63 | PathBasedResourceProvider that = (PathBasedResourceProvider) o;
64 |
65 | if(!_root.equals(that._root)) return false;
66 |
67 | return true;
68 | }
69 |
70 | @Override
71 | public int hashCode()
72 | {
73 | return _root.hashCode();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/RAMResourceProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.PathUtils;
20 | import org.linkedin.util.io.ram.RAMDirectory;
21 | import org.linkedin.util.io.ram.RAMEntry;
22 | import org.linkedin.util.io.resource.RAMResource;
23 | import org.linkedin.util.io.resource.ResourceFilter;
24 |
25 | import java.io.IOException;
26 |
27 | /**
28 | * @author ypujante@linkedin.com
29 | *
30 | */
31 | public class RAMResourceProvider extends PathBasedResourceProvider
32 | {
33 | private final RAMDirectory _root;
34 |
35 | /**
36 | * Constructor
37 | */
38 | public RAMResourceProvider(RAMDirectory root)
39 | {
40 | this(root, "/");
41 | }
42 |
43 | /**
44 | * Constructor
45 | */
46 | public RAMResourceProvider(RAMDirectory root, String rootPath)
47 | {
48 | super(rootPath);
49 | _root = root;
50 | }
51 |
52 | /**
53 | * Builds a resource given a path. Only subclasses know how to do that.
54 | *
55 | * @param path the path to the new resource (always starts with /)
56 | * @return the resource
57 | */
58 | @Override
59 | public InternalResource doBuildResource(String path)
60 | {
61 | return new RAMResource(this, getFullPath(path), path);
62 | }
63 |
64 | /**
65 | * Creates a new resource provider given the new path.
66 | *
67 | * @param rootPath
68 | * @return the new resource provider
69 | */
70 | @Override
71 | public InternalResourceProvider doCreateResourceProvider(String rootPath)
72 | {
73 | return new RAMResourceProvider(_root, getFullPath(rootPath));
74 | }
75 |
76 | /**
77 | * If the path denotes a directory, then it will return all resources that are contained in the
78 | * directory.
79 | *
80 | * @param path the path to the resource
81 | * @param filter the filter to include only some resources in the result
82 | * @return true
if it was a directory, false
otherwise
83 | * @throws IOException if there is an error accessing the resource
84 | */
85 | @Override
86 | public boolean doList(String path, ResourceFilter filter)
87 | {
88 | if(_root == null)
89 | return false;
90 |
91 | RAMEntry entry = _root.getEntryByPath(path);
92 |
93 | if(entry instanceof RAMDirectory)
94 | {
95 | RAMDirectory ramDirectory = (RAMDirectory) entry;
96 | for(RAMEntry ramEntry : ramDirectory.ls())
97 | {
98 | String resourcePath = PathUtils.addPaths(path, ramEntry.name());
99 | filter.accept(new RAMResource(this,
100 | getFullPath(resourcePath),
101 | resourcePath));
102 | }
103 | return true;
104 | }
105 | else
106 | return false;
107 | }
108 |
109 | public RAMEntry getRAMEntry(String fullpath)
110 | {
111 | return _root.getEntryByPath(fullpath);
112 | }
113 |
114 | @Override
115 | public boolean equals(Object o)
116 | {
117 | if(this == o) return true;
118 | if(o == null || getClass() != o.getClass()) return false;
119 | if(!super.equals(o)) return false;
120 |
121 | RAMResourceProvider that = (RAMResourceProvider) o;
122 |
123 | if(_root != null ? !_root.equals(that._root) : that._root != null) return false;
124 |
125 | return true;
126 | }
127 |
128 | @Override
129 | public int hashCode()
130 | {
131 | int result = super.hashCode();
132 | result = 31 * result + (_root != null ? _root.hashCode() : 0);
133 | return result;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/ResourceProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.Resource;
20 |
21 | /**
22 | * This is the base notion of a provider of resources. There will be different implementation
23 | * depending on the type of resource that needs to be returned.
24 | *
25 | * @author ypujante@linkedin.com
26 | *
27 | */
28 | public interface ResourceProvider
29 | {
30 | /**
31 | * The path to the resource is absolute. Whether it starts with / or not it will be made
32 | * absolute.
33 | *
34 | * Note that it follows the same convention as {@link java.io.File} class in the sense
35 | * that a resource simply represent a handle and does not imply that the resource exists.
36 | *
37 | * @param path the path to the resource
38 | * @return the resource given the path
39 | */
40 | Resource createResource(String path);
41 | }
42 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/SchemeURIResourceFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.Resource;
20 | import org.linkedin.util.io.resource.URIResourceFactory;
21 |
22 | import java.net.URI;
23 |
24 | /**
25 | * @author ypujante@linkedin.com
26 | *
27 | */
28 | public abstract class SchemeURIResourceFactory
29 | {
30 | /**
31 | * Constructor
32 | */
33 | public SchemeURIResourceFactory()
34 | {
35 | }
36 |
37 | /**
38 | * @return the scheme that this factory handles
39 | */
40 | public abstract String getScheme();
41 |
42 |
43 | /**
44 | * Based on the URI returns the right resource
45 | *
46 | * @param uri
47 | * @return the resource
48 | */
49 | public Resource createResource(URI uri, URIResourceFactory parent)
50 | {
51 | if(!getScheme().equals(uri.getScheme()))
52 | throw new IllegalArgumentException("cannot handle: " + uri.getScheme());
53 |
54 | return doCreateResource(uri, parent);
55 | }
56 |
57 | /**
58 | * Method that needs to be implemented by children..
59 | *
60 | * @param uri
61 | * @param parent the parent resource factory
62 | * @return the resource
63 | */
64 | protected abstract Resource doCreateResource(URI uri, URIResourceFactory parent);
65 | }
66 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/io/resource/internal/SchemeURLResourceFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.io.resource.internal;
18 |
19 | import org.linkedin.util.io.resource.Resource;
20 | import org.linkedin.util.io.resource.URIResourceFactory;
21 | import org.linkedin.util.io.resource.URLResource;
22 |
23 | import java.net.MalformedURLException;
24 | import java.net.URI;
25 |
26 | /**
27 | * Handles generic URL.. the scheme is provided. (ex: http, ftp...)
28 | *
29 | * @author ypujante@linkedin.com
30 | *
31 | */
32 | public class SchemeURLResourceFactory extends SchemeURIResourceFactory
33 | {
34 | private final String _scheme;
35 |
36 | /**
37 | * Constructor
38 | */
39 | public SchemeURLResourceFactory(String scheme)
40 | {
41 | _scheme = scheme;
42 | }
43 |
44 | /**
45 | * @return the scheme that this factory handles
46 | */
47 | @Override
48 | public String getScheme()
49 | {
50 | return _scheme;
51 | }
52 |
53 |
54 | /**
55 | * Method that needs to be implemented by children..
56 | *
57 | * @param uri
58 | * @param parent the parent resource factory
59 | * @return the resource
60 | */
61 | @Override
62 | protected Resource doCreateResource(URI uri, URIResourceFactory parent)
63 | {
64 | try
65 | {
66 | return URLResource.createFromRoot(uri.toURL());
67 | }
68 | catch(MalformedURLException e)
69 | {
70 | throw new IllegalArgumentException(uri.toString(), e);
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/CannotConfigureException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.lifecycle;
18 |
19 | import org.linkedin.util.exceptions.InternalException;
20 |
21 | /**
22 | * @author ypujante@linkedin.com */
23 | public class CannotConfigureException extends InternalException
24 | {
25 | private static final long serialVersionUID = 1L;
26 |
27 | public CannotConfigureException()
28 | {
29 | }
30 |
31 | public CannotConfigureException(String s)
32 | {
33 | super(s);
34 | }
35 |
36 | public CannotConfigureException(Throwable th)
37 | {
38 | super(th);
39 | }
40 |
41 | public CannotConfigureException(String s, Throwable throwable)
42 | {
43 | super(s, throwable);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Configurable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.lifecycle;
18 |
19 | import java.util.Map;
20 |
21 | /**
22 | * @author ypujante@linkedin.com */
23 | public interface Configurable
24 | {
25 | void configure(Map config);
26 | }
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Destroyable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.lifecycle;
18 |
19 | /**
20 | * This interface defines the API of an entity that is destroyable. The main
21 | * difference between Destroyable
and Shutdownable
22 | * is that for the entity there is nothing to wait for (in other words all the
23 | * calls to the entity are blocking calls). It is also possible to have an
24 | * entity that implements both Destroyable
and
25 | * Shutdownable
in which case, the proper way would be:
26 | *
27 | *
28 | * entity.shutdown();
29 | * entity.waitForShutdown();
30 | * // here we know that all the non blocking calls are terminated
31 | * entity.destroy();
32 | *
33 | *
34 | * @author ypujante@linkedin.com
35 | * @see Shutdownable */
36 | public interface Destroyable extends Terminable
37 | {
38 | /**
39 | * This method destroys the entity, cleaning up any resource that needs to
40 | * be cleaned up, like closing files, database connection.. */
41 | public void destroy();
42 | }
43 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Shutdown.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.lifecycle;
18 |
19 | import org.linkedin.util.annotations.Initializable;
20 | import org.linkedin.util.clock.Timespan;
21 | import org.linkedin.util.concurrent.WaitableCounter;
22 |
23 | import java.io.Serializable;
24 | import java.util.concurrent.TimeoutException;
25 |
26 | /**
27 | * Simple object that has the knowledge wether we are in shutdown or not. Works in close relation
28 | * with {@link ShutdownProxy}.
29 | *
30 | * @author ypujante@linkedin.com
31 | *
32 | */
33 | public class Shutdown implements Serializable, Shutdownable
34 | {
35 | private static final long serialVersionUID = 1L;
36 |
37 | private boolean _shutdown = false;
38 |
39 | @Initializable
40 | public WaitableCounter pendingCallsCount = new WaitableCounter();
41 |
42 | @Initializable
43 | public String module = Shutdown.class.getName();
44 |
45 | /**
46 | * Constructor
47 | */
48 | public Shutdown()
49 | {
50 | }
51 |
52 | /**
53 | * Sets the system is shutdown */
54 | @Override
55 | public synchronized void shutdown()
56 | {
57 | _shutdown = true;
58 | }
59 |
60 | /**
61 | * Waits for shutdown to be completed. After calling shutdown, there may still be some pending
62 | * work that needs to be accomplised. This method will block until it is done.
63 | *
64 | * @throws InterruptedException if interrupted while waiting
65 | * @throws IllegalStateException if shutdown has not been called
66 | */
67 | @Override
68 | public void waitForShutdown() throws InterruptedException, IllegalStateException
69 | {
70 | if(!_shutdown) throw new IllegalStateException("call shutdown first");
71 | pendingCallsCount.waitForCounter();
72 | }
73 |
74 | /**
75 | * Waits for shutdown to be completed. After calling shutdown, there may still be some pending work
76 | * that needs to be accomplised. This method will block until it is done but no longer than the
77 | * timeout.
78 | *
79 | * @param timeout how long to wait maximum for the shutdown
80 | * @throws InterruptedException if interrupted while waiting
81 | * @throws IllegalStateException if shutdown has not been called
82 | * @throws TimeoutException if shutdown still not complete after timeout
83 | */
84 | @Override
85 | public void waitForShutdown(Object timeout)
86 | throws InterruptedException, IllegalStateException, TimeoutException
87 | {
88 | if(!_shutdown) throw new IllegalStateException("call shutdown first");
89 | pendingCallsCount.waitForCounter(timeout);
90 | }
91 |
92 | /**
93 | * Called right before executing a call
94 | *
95 | * @throws ShutdownRequestedException
96 | */
97 | synchronized void startCall() throws ShutdownRequestedException
98 | {
99 | if(_shutdown)
100 | throw new ShutdownRequestedException(module);
101 |
102 | pendingCallsCount.inc();
103 | }
104 |
105 | /**
106 | * MUST be called if {@link #startCall()} is called after the call (typically in a
107 | * finally
)
108 | */
109 | void endCall()
110 | {
111 | pendingCallsCount.dec();
112 | }
113 |
114 | /**
115 | * @return the number of currently pending calls
116 | */
117 | public int getPendingCallsCount()
118 | {
119 | return pendingCallsCount.getCounter();
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/ShutdownRequestedException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.lifecycle;
18 |
19 | import org.linkedin.util.exceptions.InternalException;
20 |
21 | /**
22 | * Thrown when shutdown has been requested. As a result the method cannot
23 | * be executed.
24 | *
25 | * @author ypujante@linkedin.com
26 | */
27 | public class ShutdownRequestedException extends InternalException
28 | {
29 | private static final long serialVersionUID = 1L;
30 |
31 | /**
32 | * Constructor */
33 | public ShutdownRequestedException(String module)
34 | {
35 | super(module);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Shutdownable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.lifecycle;
18 |
19 | import org.linkedin.util.clock.ClockUtils;
20 | import org.linkedin.util.clock.Timespan;
21 |
22 | import java.util.concurrent.TimeoutException;
23 |
24 | /**
25 | * Defines the method of an entity that is shutdownable
26 | *
27 | * @author ypujante@linkedin.com */
28 | public interface Shutdownable extends Terminable
29 | {
30 | /**
31 | * This methods sets the entity in shutdown mode. Any method call on this
32 | * entity after shutdown should be either rejected
33 | * (IllegalStateException
) or discarded. This method should
34 | * not block and return immediately.
35 | *
36 | * @see #waitForShutdown() */
37 | public void shutdown();
38 |
39 | /**
40 | * Waits for shutdown to be completed. After calling shutdown, there may
41 | * still be some pending work that needs to be accomplised. This method
42 | * will block until it is done.
43 | *
44 | * @exception InterruptedException if interrupted while waiting
45 | * @exception IllegalStateException if shutdown has not been called */
46 | public void waitForShutdown()
47 | throws InterruptedException, IllegalStateException;
48 |
49 | /**
50 | * Waits for shutdown to be completed. After calling shutdown, there may
51 | * still be some pending work that needs to be accomplised. This method
52 | * will block until it is done but no longer than the timeout.
53 | *
54 | * @param timeout how long to wait maximum for the shutdown
55 | * (see {@link ClockUtils#toTimespan(Object)})
56 | * @exception InterruptedException if interrupted while waiting
57 | * @exception IllegalStateException if shutdown has not been called
58 | * @exception TimeoutException if shutdown still not complete after timeout */
59 | public void waitForShutdown(Object timeout)
60 | throws InterruptedException, IllegalStateException, TimeoutException;
61 | }
62 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Startable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.lifecycle;
18 |
19 | /**
20 | * Defines an entity that can be started.
21 | *
22 | * @author ypujante@linkedin.com
23 | *
24 | */
25 | public interface Startable
26 | {
27 | /**
28 | * This method must NOT block and should start the entity and return right away.
29 | */
30 | void start();
31 | }
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/lifecycle/Terminable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.lifecycle;
18 |
19 | /**
20 | * This is simply a marker interface that defines the fact that an entity can
21 | * be terminated (shutdown, destroy)
22 | *
23 | * @author ypujante@linkedin.com */
24 | public interface Terminable
25 | {
26 | }
27 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/reflect/NullClassLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 |
18 | package org.linkedin.util.reflect;
19 |
20 | import java.net.URL;
21 |
22 | /**
23 | * Null pattern for class loader...
24 | *
25 | * @author ypujante@linkedin.com
26 | *
27 | */
28 | public class NullClassLoader extends ClassLoader
29 | {
30 | public static final NullClassLoader INSTANCE = new NullClassLoader();
31 |
32 | public static NullClassLoader instance()
33 | {
34 | return INSTANCE;
35 | }
36 |
37 | /**
38 | * Constructor
39 | */
40 | public NullClassLoader()
41 | {
42 | }
43 |
44 | @Override
45 | public Class> loadClass(String name) throws ClassNotFoundException
46 | {
47 | throw new ClassNotFoundException(name);
48 | }
49 |
50 | @Override
51 | public URL getResource(String name)
52 | {
53 | return null;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/reflect/ObjectProxy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.reflect;
18 |
19 | /**
20 | * This interface represents an object proxied. It will most likely be implemented by invocation
21 | * handlers when using dynamic proxy. The concept of {@link java.lang.reflect.Proxy} does not
22 | * necessarily represent a proxy over an object. This interface is meant to specify this restriction
23 | * which is 99% of the cases in which we use dynamic proxies!
24 | *
25 | * @author ypujante@linkedin.com
26 | *
27 | */
28 | public interface ObjectProxy
29 | {
30 | /**
31 | * @return the object proxied */
32 | T getProxiedObject();
33 | }
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/reflect/ObjectProxyBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 |
18 | package org.linkedin.util.reflect;
19 |
20 |
21 | import java.lang.reflect.InvocationHandler;
22 | import java.lang.reflect.Proxy;
23 | import java.util.ArrayList;
24 | import java.util.Collection;
25 | import java.util.List;
26 |
27 | /**
28 | * @author ypujante@linkedin.com
29 | *
30 | */
31 | public class ObjectProxyBuilder
32 | {
33 | /**
34 | * Convenient call which creates a proxy using the handler and the interface. It will also
35 | * check that the object bien proxied (if implements ObjectProxy
) properly
36 | * implement the interface...
37 | *
38 | * @return the proxy (which implement all the interface)
39 | */
40 | @SuppressWarnings("unchecked")
41 | public static T createProxy(InvocationHandler handler, Class itface)
42 | {
43 | if(handler instanceof ObjectProxy)
44 | {
45 | ObjectProxy proxy = (ObjectProxy) handler;
46 | if(!ReflectUtils.isSubClassOrInterfaceOf(proxy.getProxiedObject().getClass(), itface))
47 | throw new IllegalArgumentException(proxy.getProxiedObject().getClass() + " does not extend " + itface);
48 | }
49 |
50 | return (T) Proxy.newProxyInstance(itface.getClassLoader(),
51 | new Class>[] {itface},
52 | handler);
53 | }
54 |
55 | /**
56 | * Convenient call which creates a proxy using the handler and the interfaces. It will also
57 | * check that the object bien proxied (if implements ObjectProxy
) properly
58 | * implement the right interfaces...
59 | *
60 | * @return the proxy (which implement all the provided interfaces)
61 | */
62 | public static Object createProxy(InvocationHandler handler, Class>... itfaces)
63 | {
64 | if(handler instanceof ObjectProxy)
65 | {
66 | ObjectProxy proxy = (ObjectProxy) handler;
67 | Class> proxyClass = proxy.getProxiedObject().getClass();
68 | for(Class> itface : itfaces)
69 | {
70 | if(!ReflectUtils.isSubClassOrInterfaceOf(proxyClass, itface))
71 | throw new IllegalArgumentException(proxyClass + " does not extend " + itface);
72 | }
73 | }
74 |
75 | List classLoaders = new ArrayList();
76 | for(Class> itface : itfaces)
77 | {
78 | classLoaders.add(itface.getClassLoader());
79 | }
80 |
81 | ClassLoader classLoader = ClassLoaderChain.createChain(classLoaders);
82 |
83 | return Proxy.newProxyInstance(classLoader,
84 | itfaces,
85 | handler);
86 | }
87 |
88 | /**
89 | * @see #createProxy(InvocationHandler, Class[])
90 | */
91 | public static Object createProxy(InvocationHandler handler, Collection> interfaces)
92 | {
93 | return createProxy(handler, interfaces.toArray(new Class[interfaces.size()]));
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/reflect/ObjectProxyInvocationHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.reflect;
18 |
19 | import java.lang.reflect.InvocationHandler;
20 | import java.lang.reflect.Proxy;
21 | import java.lang.reflect.Method;
22 | import java.lang.reflect.InvocationTargetException;
23 |
24 | /**
25 | * Very basic implementation of the proxy which simply delegates all calls to the proxied object.
26 | *
27 | * @author ypujante@linkedin.com
28 | *
29 | */
30 | public class ObjectProxyInvocationHandler implements ObjectProxy, InvocationHandler
31 | {
32 | private final T _proxiedObject;
33 |
34 | /**
35 | * Constructor
36 | */
37 | public ObjectProxyInvocationHandler(T proxiedObject)
38 | {
39 | _proxiedObject = proxiedObject;
40 | }
41 |
42 | /**
43 | * @return the object proxied
44 | */
45 | @Override
46 | public T getProxiedObject()
47 | {
48 | return _proxiedObject;
49 | }
50 |
51 | @Override
52 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
53 | {
54 | try
55 | {
56 | return method.invoke(_proxiedObject, args);
57 | }
58 | catch(InvocationTargetException e)
59 | {
60 | throw e.getTargetException();
61 | }
62 | }
63 |
64 | /**
65 | * This is a convenient call when you want to proxy an object with the unique given
66 | * interface. Note that you can use the more general call {@link Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}
67 | * if you want to do something different.
68 | *
69 | * @param interfaceToProxy the interface to proxy
70 | * @param objectToProxy the object to proxy (note that it must implement interfaceToProxy!)
71 | * @return the proxied object */
72 | @SuppressWarnings("unchecked")
73 | public static T createProxy(Class interfaceToProxy, T objectToProxy)
74 | {
75 | // since there is only one interface in the array, we know that the proxy must implement it!
76 | return (T) Proxy.newProxyInstance(interfaceToProxy.getClassLoader(),
77 | new Class>[] {interfaceToProxy},
78 | new ObjectProxyInvocationHandler(objectToProxy));
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/text/IdentityString.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.text;
18 |
19 | import org.linkedin.util.reflect.ObjectProxy;
20 |
21 | import java.lang.reflect.Array;
22 | import java.lang.reflect.Proxy;
23 | import java.lang.reflect.InvocationHandler;
24 |
25 | /**
26 | * @author ypujante@linkedin.com
27 | *
28 | */
29 | public class IdentityString
30 | {
31 | public final static IdentityString FULL_IDENTITY_STRING =
32 | new IdentityString(new ClassNameExtractor()
33 | {
34 | @Override
35 | public String getClassName(Object o)
36 | {
37 | return o.getClass().getName();
38 | }
39 | });
40 |
41 | public final static IdentityString SHORT_IDENTITY_STRING =
42 | new IdentityString(new ClassNameExtractor()
43 | {
44 | @Override
45 | public String getClassName(Object o)
46 | {
47 | return o.getClass().getSimpleName();
48 | }
49 | });
50 |
51 | private static interface ClassNameExtractor
52 | {
53 | String getClassName(Object o);
54 | }
55 |
56 | private final ClassNameExtractor _classNameExtractor;
57 |
58 | /**
59 | * Constructor
60 | */
61 | public IdentityString(ClassNameExtractor classNameExtractor)
62 | {
63 | _classNameExtractor = classNameExtractor;
64 | }
65 |
66 | public String getIdentity(Object o)
67 | {
68 | if(o == null)
69 | return "null";
70 |
71 | if(o.getClass().isArray())
72 | {
73 | int len = Array.getLength(o);
74 | StringBuilder sb = new StringBuilder();
75 | for(int i = 0; i < len; i++)
76 | {
77 | if(i > 0)
78 | sb.append(",");
79 | sb.append(getIdentity(Array.get(o, i)));
80 | }
81 | return sb.toString();
82 | }
83 |
84 | StringBuilder sb = new StringBuilder();
85 |
86 | sb.append(_classNameExtractor.getClassName(o)).append('@').append(Integer.toHexString(System.identityHashCode(o)));
87 |
88 | if(Proxy.isProxyClass(o.getClass()))
89 | {
90 | InvocationHandler invocationHandler = Proxy.getInvocationHandler(o);
91 | if(invocationHandler instanceof ObjectProxy)
92 | {
93 | ObjectProxy objectProxy = (ObjectProxy) invocationHandler;
94 | Object proxiedObject = objectProxy.getProxiedObject();
95 |
96 | sb.append(" (proxy of: ").append(getIdentity(proxiedObject)).append(")");
97 | }
98 | }
99 |
100 | return sb.toString();
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/text/TextUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 |
18 | package org.linkedin.util.text;
19 |
20 | /**
21 | * @author ypujante@linkedin.com
22 | *
23 | */
24 | public class TextUtils
25 | {
26 |
27 | /**
28 | * @param s the string to test
29 | * @return true iff s is null or if s contains only whitespace.
30 | */
31 | public static boolean isEmptyString(String s)
32 | {
33 | return s == null || s.trim().length() == 0;
34 | }
35 |
36 | /**
37 | * Searches in the string 's
' all occurences of the
38 | * substring 'src
' and replaces it with the string
39 | * 'dst
'.
40 | *
41 | * @param s the string to search
42 | * @param src the substring to search for inside s
43 | * @param dst the replacing string
44 | * @return the string with the text replaced */
45 | public static String searchAndReplace(String s, String src, String dst)
46 | {
47 | if(s == null)
48 | return null;
49 |
50 | StringBuilder result = new StringBuilder();
51 |
52 | int i = 0;
53 | int len = s.length();
54 | int len2 = src.length();
55 |
56 | while(i < len)
57 | {
58 | int index = s.indexOf(src, i);
59 | if(index == -1)
60 | {
61 | if(i == 0)
62 | return s;
63 |
64 | result.append(s.substring(i));
65 | break;
66 | }
67 |
68 | result.append(s.substring(i, index));
69 | result.append(dst);
70 |
71 | i = index + len2;
72 | }
73 |
74 | return result.toString();
75 | }
76 |
77 | /**
78 | * Constructor
79 | */
80 | private TextUtils()
81 | {
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/url/FilteredURL.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.url;
18 |
19 | import java.io.Serializable;
20 | import java.util.List;
21 |
22 | /**
23 | * Simple filter on URL
24 | *
25 | * @author ypujante@linkedin.com
26 | *
27 | */
28 | public class FilteredURL implements URL, Serializable
29 | {
30 | private final static long serialVersionUID = 1L;
31 | private final URL _urlToFilter;
32 |
33 | /**
34 | * Constructor
35 | */
36 | public FilteredURL(URL urlToFilter)
37 | {
38 | _urlToFilter = urlToFilter;
39 | }
40 |
41 | public URL getFilteredURL()
42 | {
43 | return _urlToFilter;
44 | }
45 |
46 | @Override
47 | public URL createRelativeURL()
48 | {
49 | return _urlToFilter.createRelativeURL();
50 | }
51 |
52 | @Override
53 | public String getFragment()
54 | {
55 | return _urlToFilter.getFragment();
56 | }
57 |
58 | @Override
59 | public boolean getHasFragment()
60 | {
61 | return _urlToFilter.getHasFragment();
62 | }
63 |
64 | @Override
65 | public boolean getHasHost()
66 | {
67 | return _urlToFilter.getHasHost();
68 | }
69 |
70 | @Override
71 | public boolean getHasPath()
72 | {
73 | return _urlToFilter.getHasPath();
74 | }
75 |
76 | @Override
77 | public boolean getHasPort()
78 | {
79 | return _urlToFilter.getHasPort();
80 | }
81 |
82 | @Override
83 | public boolean getHasQueryParameters()
84 | {
85 | return _urlToFilter.getHasQueryParameters();
86 | }
87 |
88 | @Override
89 | public boolean getHasScheme()
90 | {
91 | return _urlToFilter.getHasScheme();
92 | }
93 |
94 | @Override
95 | public boolean getHasUserInfo()
96 | {
97 | return _urlToFilter.getHasUserInfo();
98 | }
99 |
100 | @Override
101 | public String getHost()
102 | {
103 | return _urlToFilter.getHost();
104 | }
105 |
106 | @Override
107 | public String getPath()
108 | {
109 | return _urlToFilter.getPath();
110 | }
111 |
112 | @Override
113 | public List getPathComponents()
114 | {
115 | return _urlToFilter.getPathComponents();
116 | }
117 |
118 | @Override
119 | public int getPort()
120 | {
121 | return _urlToFilter.getPort();
122 | }
123 |
124 | @Override
125 | public Query getQuery()
126 | {
127 | return _urlToFilter.getQuery();
128 | }
129 |
130 | @Override
131 | public String getQueryString()
132 | {
133 | return _urlToFilter.getQueryString();
134 | }
135 |
136 | @Override
137 | public String getScheme()
138 | {
139 | return _urlToFilter.getScheme();
140 | }
141 |
142 | @Override
143 | public String getURL()
144 | {
145 | return _urlToFilter.getURL();
146 | }
147 |
148 | @Override
149 | public String getUserInfo()
150 | {
151 | return _urlToFilter.getUserInfo();
152 | }
153 |
154 | /**
155 | * @return this object as a {@link URL}
156 | */
157 | @Override
158 | public java.net.URL toJavaURL()
159 | {
160 | return _urlToFilter.toJavaURL();
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/url/Query.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.url;
18 |
19 | import java.util.Iterator;
20 | import java.util.Map;
21 |
22 | /**
23 | * The interface which defines the query in a url. Only accessors.
24 | *
25 | * @author ypujante@linkedin.com
26 | */
27 | public interface Query
28 | {
29 | /**
30 | * @return true
if query parameters have been added */
31 | boolean getHasQueryParameters();
32 |
33 | /**
34 | * @return the iterator of parameter names */
35 | Iterator getParameterNames();
36 |
37 | /**
38 | * @return the query as a string */
39 | String getQuery();
40 |
41 | /**
42 | * Gets the parameters given its name
43 | *
44 | * @param name the name of the parameter
45 | * @return the parameters or null
if none found*/
46 | String[] getParameterValues(String name);
47 |
48 | /**
49 | * @return the parameter map */
50 | Map getParameterMap();
51 |
52 | /**
53 | * Get the first parameter given its name
54 | *
55 | * @param name the name of the parameter
56 | * @return the first parameter */
57 | String getParameter(String name);
58 |
59 | /**
60 | * @return the encoding used by the query */
61 | String getEncoding();
62 |
63 | /**
64 | * Gets the first parameter given its name and converts it to the given boolean type.
65 | *
66 | * @param name the name of the parameter
67 | * @return true if parmaeterValue equals the name that is given, or if it is one of the following strings
68 | * 'yes', 'true', 'on'
69 | */
70 | boolean getBooleanParameter(String name);
71 |
72 | /**
73 | * Gets the first parameter given its name and converts it to int
74 | * @param name
75 | * @param defaultValue
76 | * @return return an int, if parameter not found or parse exception, return default value
77 | */
78 | int getIntParameter(String name, int defaultValue);
79 | }
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/url/URL.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.url;
18 |
19 | import java.util.List;
20 |
21 | /**
22 | * Interface which defines a url. Only accessors.
23 | *
24 | * @author ypujante@linkedin.com
25 | */
26 | public interface URL
27 | {
28 | /**
29 | * @return the path */
30 | String getPath();
31 |
32 | /**
33 | * If the path is /a/b/c then returns a list containing 3 elements "a", "b" and "c"
34 | * @return the path splitted at each '/' and decoded
35 | */
36 | List getPathComponents();
37 |
38 | /**
39 | * @return the fragment */
40 | String getFragment();
41 |
42 | /**
43 | * @return the query string */
44 | String getQueryString();
45 |
46 | /**
47 | * @return the query */
48 | Query getQuery();
49 |
50 | /**
51 | * @return true
if a path has been set */
52 | boolean getHasPath();
53 |
54 | /**
55 | * @return true
if the fragment has been set */
56 | boolean getHasFragment();
57 |
58 | /**
59 | * @return true
if query parameters have been added */
60 | boolean getHasQueryParameters();
61 |
62 | /**
63 | * @return the url */
64 | String getURL();
65 |
66 | String getScheme();
67 |
68 | boolean getHasScheme();
69 |
70 | String getUserInfo();
71 |
72 | boolean getHasUserInfo();
73 |
74 | String getHost();
75 |
76 | boolean getHasHost();
77 |
78 | int getPort();
79 |
80 | boolean getHasPort();
81 |
82 | /**
83 | * @return a url which is relative (does not contain anything before path)
84 | */
85 | public URL createRelativeURL();
86 |
87 | /**
88 | * @return this object as a {@link java.net.URL}
89 | */
90 | public java.net.URL toJavaURL();
91 | }
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/url/URLCodec.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.url;
18 |
19 | import org.linkedin.util.text.TextUtils;
20 |
21 | import java.io.UnsupportedEncodingException;
22 | import java.io.Serializable;
23 | import java.net.URLEncoder;
24 | import java.net.URLDecoder;
25 |
26 | /**
27 | * @author ypujante@linkedin.com
28 | *
29 | */
30 | public class URLCodec implements Serializable
31 | {
32 | private static final long serialVersionUID = 1L;
33 |
34 | public static final URLCodec INSTANCE = new URLCodec(false);
35 |
36 | public static URLCodec instance()
37 | {
38 | return INSTANCE;
39 | }
40 |
41 | public static final String CHARACTER_ENCODING = "UTF-8";
42 |
43 | private final boolean _encodeDot;
44 | private final String _characterEncoding;
45 |
46 | /**
47 | * Constructor
48 | */
49 | public URLCodec(boolean encodeDot, String characterEncoding)
50 | throws UnsupportedEncodingException
51 | {
52 | _encodeDot = encodeDot;
53 | "".getBytes(characterEncoding); // checks for availabitity of encoding
54 | _characterEncoding = characterEncoding;
55 | }
56 |
57 | /**
58 | * Constructor
59 | */
60 | public URLCodec(boolean encodeDot)
61 | {
62 | _encodeDot = encodeDot;
63 | _characterEncoding = CHARACTER_ENCODING; // we know that it is supported!
64 | }
65 |
66 | /**
67 | * Constructor
68 | */
69 | public URLCodec()
70 | {
71 | this(false);
72 | }
73 |
74 | public String getCharacterEncoding()
75 | {
76 | return _characterEncoding;
77 | }
78 |
79 | public boolean isEncodeDot()
80 | {
81 | return _encodeDot;
82 | }
83 |
84 | /**
85 | * Encapsulates the call to encoding a URL
86 | *
87 | * @param original the string to encode
88 | * @return the encoded url */
89 | public String urlEncode(String original)
90 | {
91 | // see http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars
92 | // for an explanation of the character encoding
93 | String s = null;
94 | try
95 | {
96 | s = URLEncoder.encode(original, _characterEncoding);
97 | }
98 | catch(UnsupportedEncodingException e)
99 | {
100 | throw new RuntimeException(e);
101 | }
102 |
103 | if(_encodeDot)
104 | {
105 | // we encode . as well because it can cause problems in url in emails.
106 | s = TextUtils.searchAndReplace(s, ".", "%2E");
107 | }
108 |
109 | return s;
110 | }
111 |
112 | /**
113 | * Encapsulates the call to decoding a URL so that we don't have to deal
114 | * with the encoding.
115 | *
116 | * @param original the string to decode
117 | * @return the encoded url */
118 | public String urlDecode(String original)
119 | {
120 | try
121 | {
122 | return URLDecoder.decode(original, _characterEncoding);
123 | }
124 | catch(UnsupportedEncodingException e)
125 | {
126 | throw new RuntimeException(e);
127 | }
128 | }
129 |
130 | @Override
131 | public boolean equals(Object o)
132 | {
133 | if(this == o) return true;
134 | if(o == null || getClass() != o.getClass()) return false;
135 |
136 | URLCodec urlCodec = (URLCodec) o;
137 |
138 | if(_encodeDot != urlCodec._encodeDot) return false;
139 | if(_characterEncoding != null ?
140 | !_characterEncoding.equals(urlCodec._characterEncoding) :
141 | urlCodec._characterEncoding != null) return false;
142 |
143 | return true;
144 | }
145 |
146 | @Override
147 | public int hashCode()
148 | {
149 | int result = (_encodeDot ? 1 : 0);
150 | result = 31 * result + (_characterEncoding != null ? _characterEncoding.hashCode() : 0);
151 | return result;
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/main/java/org/linkedin/util/xml/AbstractXMLBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.util.xml;
18 |
19 | import java.util.Map;
20 |
21 | /**
22 | * Define some methods in terms of others so that there is less code to
23 | * implement in further implementation.
24 | *
25 | * @author ypujante@linkedin.com */
26 | public abstract class AbstractXMLBuilder implements XMLBuilder
27 | {
28 | /**
29 | * Constructor */
30 | public AbstractXMLBuilder()
31 | {
32 | }
33 |
34 | /**
35 | * Adds a tag
36 | *
37 | * @param tagName the name of the tag to add
38 | * @param value the value of the tag to add */
39 | @Override
40 | public void addTag(String tagName, int value)
41 | {
42 | addTag(tagName, String.valueOf(value));
43 | }
44 |
45 | /**
46 | * Adds a tag
47 | *
48 | * @param tagName the name of the tag to add
49 | * @param value the value of the tag to add */
50 | @Override
51 | public void addTag(String tagName, double value)
52 | {
53 | addTag(tagName, String.valueOf(value));
54 | }
55 |
56 | /**
57 | * Adds a tag which contains an attribute
58 | *
59 | * @param tagName the name of the tag to add
60 | * @param value the value of the tag to add
61 | * @param attrName the name of the attribute
62 | * @param attrValue the value of the attribute */
63 | @Override
64 | public void addTag(String tagName,
65 | int value,
66 | String attrName,
67 | String attrValue)
68 | {
69 | addTag(tagName, String.valueOf(value), attrName, attrValue);
70 | }
71 |
72 | /**
73 | * Adds a tag which contains an attribute
74 | *
75 | * @param tagName the name of the tag to add
76 | * @param value the value of the tag to add
77 | * @param attrName the name of the attribute
78 | * @param attrValue the value of the attribute */
79 | @Override
80 | public void addTag(String tagName,
81 | double value,
82 | String attrName,
83 | String attrValue)
84 | {
85 | addTag(tagName, String.valueOf(value), attrName, attrValue);
86 | }
87 |
88 | /**
89 | * Adds a tag which contains the attributes specified. All the
90 | * properties will be turned into attributes.
91 | *
92 | * @param tagName the name of the tag to add
93 | * @param value the value of the tag to add
94 | * @param attributes the attributes */
95 | @Override
96 | public void addTag(String tagName, int value, Map attributes)
97 | {
98 | addTag(tagName, String.valueOf(value), attributes);
99 | }
100 |
101 | /**
102 | * Adds a tag which contains the attributes specified. All the
103 | * properties will be turned into attributes.
104 | *
105 | * @param tagName the name of the tag to add
106 | * @param value the value of the tag to add
107 | * @param attributes the attributes */
108 | @Override
109 | public void addTag(String tagName, double value, Map attributes)
110 | {
111 | addTag(tagName, String.valueOf(value), attributes);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/org.linkedin.util-core/src/test/java/org/linkedin/util/io/resource/TestNullResource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 |
18 | package org.linkedin.util.io.resource;
19 |
20 | import junit.framework.TestCase;
21 |
22 | import java.io.IOException;
23 |
24 | /**
25 | * @author ypujante@linkedin.com
26 | *
27 | */
28 | public class TestNullResource extends TestCase
29 | {
30 | /**
31 | * Constructor
32 | */
33 | public TestNullResource(String name)
34 | {
35 | super(name);
36 | }
37 |
38 | public void testNullResource() throws IOException
39 | {
40 | NullResource r = NullResource.createFromRoot("/a/b");
41 |
42 | checkNullResource(r);
43 | assertEquals("/", r.getPath());
44 | assertEquals("", r.getFilename());
45 | assertEquals("nullResource:/a/b", r.toURI().toString());
46 |
47 | r = (NullResource) r.createRelative("/c");
48 | checkNullResource(r);
49 | assertEquals("/c", r.getPath());
50 | assertEquals("c", r.getFilename());
51 | assertEquals("nullResource:/a/b/c", r.toURI().toString());
52 |
53 | r = (NullResource) r.createRelative("/d");
54 | checkNullResource(r);
55 | assertEquals("/c/d", r.getPath());
56 | assertEquals("d", r.getFilename());
57 | assertEquals("nullResource:/a/b/c/d", r.toURI().toString());
58 |
59 | r = (NullResource) r.getParentResource();
60 | checkNullResource(r);
61 | assertEquals("/c", r.getPath());
62 | assertEquals("c", r.getFilename());
63 | assertEquals("nullResource:/a/b/c", r.toURI().toString());
64 | }
65 |
66 | private void checkNullResource(Resource r) throws IOException
67 | {
68 | assertFalse(r.exists());
69 | assertFalse(r.isDirectory());
70 | assertEquals(0L, r.lastModified());
71 | assertEquals(0L, r.length());
72 | assertNull(r.list());
73 |
74 | try
75 | {
76 | r.getInfo();
77 | fail("should fail with excpetion");
78 | }
79 | catch(IOException e)
80 | {
81 | // ok
82 | }
83 | try
84 | {
85 | r.getInputStream();
86 | fail("should fail with excpetion");
87 | }
88 | catch(IOException e)
89 | {
90 | // ok
91 | }
92 | try
93 | {
94 | r.getFile();
95 | fail("should fail with excpetion");
96 | }
97 | catch(IOException e)
98 | {
99 | // ok
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | * Portions Copyright 2012-2013 Yan Pujante
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 | * use this file except in compliance with the License. You may obtain a copy of
7 | * 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, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | apply plugin: 'groovy'
19 | apply plugin: 'org.linkedin.release'
20 |
21 | dependencies {
22 | compile project(':org.linkedin.util-core')
23 | compile spec.external.ant
24 | compile spec.external.slf4j
25 | compile spec.external.slf4jJul
26 | compile spec.external.log4j
27 | compile spec.external.json
28 | compile spec.external.jacksoncore
29 | compile spec.external.jacksondatabind
30 | compile spec.external.groovy
31 |
32 | testCompile spec.external.junit
33 | testRuntime spec.external.slf4jLog4j
34 | }
35 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/ant/AntUtils.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | * Portions Copyright (c) 2011-2013 Yan Pujante
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 | * use this file except in compliance with the License. You may obtain a copy of
7 | * 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, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 |
19 | package org.linkedin.groovy.util.ant
20 |
21 | import org.apache.tools.ant.Project
22 | import org.apache.tools.ant.BuildException
23 | import org.apache.tools.ant.RuntimeConfigurable
24 | import org.apache.tools.ant.Target
25 | import org.apache.tools.ant.Task
26 |
27 | /**
28 | * Helper methods for ant
29 | *
30 | * @author ypujante@linkedin.com
31 | */
32 | class AntUtils
33 | {
34 | /**
35 | * Executes the closure with a builder and make sure to catch BuildException
36 | * to propertly unwrap them
37 | */
38 | static def withBuilder(Closure closure)
39 | {
40 | AntBuilder6068 builder = new AntBuilder6068()
41 | // removes info messages...
42 | builder.project.buildListeners[0].messageOutputLevel = Project.MSG_WARN
43 | try
44 | {
45 | return closure(builder)
46 | }
47 | catch(BuildException e)
48 | {
49 | if(e.cause)
50 | throw e.cause
51 | else
52 | throw e
53 | }
54 | }
55 |
56 | /**
57 | * Creates the directory and parents of the provided directory. Returns dir.
58 | */
59 | static File mkdirs(File dir)
60 | {
61 | AntUtils.withBuilder { ant -> ant.mkdir(dir: dir) }
62 | return dir
63 | }
64 |
65 | /**
66 | * Returns a temp file located in System.getProperty('java.io.tmpdir')
67 | */
68 | static File tempFile()
69 | {
70 | return tempFile([:])
71 | }
72 |
73 | /**
74 | * Creates a temp file:
75 | *
76 | * @param args.destdir where the file should be created (optional (will go in
77 | * System.getProperty('java.io.tmpdir')
)
78 | * @param args.prefix a prefix for the file (optional)
79 | * @param args.suffix a suffix for the file (optional)
80 | * @param args.deleteonexit if the temp file should be deleted on exit (default to
81 | * false
)
82 | * @param args.createParents if the parent directories should be created (default to
83 | * true
)
84 | * @return a file (note that it is just a file object and that the actual file has *not* been
85 | * created and the parents may have been depending on the args.createParents value)
86 | */
87 | static File tempFile(args)
88 | {
89 | args = args ?: [:]
90 | args = new HashMap(args)
91 | args.destdir = args.destdir ?: System.getProperty('java.io.tmpdir')
92 | args.prefix = args.prefix ?: ''
93 | args.deleteonexit = args.deleteonexit ?: false
94 | args.property = 'p'
95 | def tempFile = AntUtils.withBuilder { ant -> ant.tempfile(args).project.getProperty('p') }
96 | tempFile = new File(tempFile)
97 | if(args.createParents == null ? true : args.createParent)
98 | {
99 | mkdirs(tempFile.parentFile)
100 | }
101 | return tempFile
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/cli/CliUtils.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.groovy.util.cli
18 |
19 | /**
20 | * Utilities methods for cli (cli builder)
21 | *
22 | * @author ypujante@linkedin.com
23 | */
24 | class CliUtils
25 | {
26 | /**
27 | * Parses the cli options and returns them as well as a ConfigObject
where each key
28 | * is the long option and value is the value of the option
29 | *
30 | * @param params.cli the CliBuilder
instance (required)
31 | * @param params.args the command line arguments (required)
32 | * @param params.configFileOption the (short) name of an option that would contain a config file
33 | * to read (optional)
34 | * @return a map [config: c, options: o]
35 | */
36 |
37 | static def parseCliOptions(params)
38 | {
39 | def options = params.cli.parse(params.args)
40 |
41 | if(!options)
42 | {
43 | params.cli.usage()
44 | return null
45 | }
46 |
47 | Properties properties = new Properties()
48 |
49 | if(params.configFileOption)
50 | {
51 | def configFile = options."${params.configFileOption}"
52 | if(configFile)
53 | {
54 | new File(configFile).withInputStream {
55 | properties.load(it)
56 | }
57 | }
58 | }
59 |
60 | params.cli.options.options.each { option ->
61 | def value = options."${option.opt}"
62 | if(value != false)
63 | properties[option.longOpt] = value
64 | }
65 |
66 | [
67 | config: new ConfigSlurper().parse(properties),
68 | options: options
69 | ]
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/config/Config.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.groovy.util.config
18 |
19 | /**
20 | * @author ypujante@linkedin.com
21 | */
22 | class Config
23 | {
24 | static String getRequiredString(config, String name)
25 | {
26 | String value = getOptionalString(config, name, null)
27 | if(value == null)
28 | throw new MissingConfigParameterException(name)
29 | return value
30 | }
31 |
32 | static String getOptionalString(config, String name, String defaultValue)
33 | {
34 | def value = config?."${name}"
35 |
36 | if(value == null)
37 | value = defaultValue
38 |
39 | return value?.toString()
40 | }
41 |
42 | static boolean getOptionalBoolean(config, String name, boolean defaultValue)
43 | {
44 | def value = config?."${name}"
45 |
46 | String param = value?.toString()?.toLowerCase()
47 |
48 | if(param == null)
49 | return defaultValue
50 |
51 | switch(param)
52 | {
53 | case 'true':
54 | case 'yes':
55 | case 'on':
56 | return true
57 |
58 | case 'false':
59 | case 'no':
60 | case 'off':
61 | return false
62 | }
63 |
64 | throw new IllegalArgumentException("not a boolean : " + param);
65 | }
66 |
67 | static int getOptionalInt(config, String name, int defaultValue)
68 | {
69 | def value = config?."${name}"
70 |
71 | if(value == null)
72 | return defaultValue
73 |
74 | return value as int
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/config/MissingConfigParameterException.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.groovy.util.config
18 |
19 | /**
20 | * @author ypujante@linkedin.com
21 | */
22 | class MissingConfigParameterException extends RuntimeException
23 | {
24 | private static final long serialVersionUID = 1L;
25 |
26 | public MissingConfigParameterException() { super(); }
27 | public MissingConfigParameterException(String msg) { super(msg); }
28 | }
29 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/ivy/IvyURLHandler.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | * Portions Copyright (c) 2011 Yan Pujante
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 | * use this file except in compliance with the License. You may obtain a copy of
7 | * 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, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package org.linkedin.groovy.util.ivy
19 |
20 | import groovy.xml.NamespaceBuilder
21 | import org.linkedin.groovy.util.io.GroovyIOUtils
22 | import org.linkedin.util.io.PathUtils
23 | import org.linkedin.groovy.util.ant.AntUtils
24 |
25 | /**
26 | * Handle ivy:/organisation/name/version
style urls
27 | *
28 | * @author ypujante@linkedin.com */
29 | class IvyURLHandler extends URLStreamHandler
30 | {
31 | private final def _defaultIvySettings
32 |
33 | IvyURLHandler(defaultIvySettings)
34 | {
35 | _defaultIvySettings = defaultIvySettings
36 | }
37 |
38 | protected URLConnection openConnection(URL url)
39 | {
40 | def ivyCoordinates = PathUtils.removeLeadingSlash(url.path).split('/')
41 | return new IvyURLConnection(url, _defaultIvySettings, ivyCoordinates);
42 | }
43 |
44 | protected void parseURL(URL u, String spec, int start, int limit)
45 | {
46 | super.parseURL(u, spec, start, limit)
47 |
48 | if(u.getHost() || u.getPort() != -1)
49 | throw new UnsupportedOperationException("host/port not supported yet")
50 |
51 | if(u.getQuery())
52 | throw new IllegalArgumentException("no query string is allowed")
53 |
54 | def ivyCoordinates = PathUtils.removeLeadingSlash(u.path).split('/')
55 | if(ivyCoordinates.size() < 3 || ivyCoordinates.size() > 4)
56 | throw new IllegalArgumentException("Bad ivy coordinates: ${u}")
57 | }
58 | }
59 |
60 | /**
61 | * Handle ivy:/organisation/name/version
style urls
62 | *
63 | * @author ypujante@linkedin.com */
64 | class IvyURLConnection extends URLConnection
65 | {
66 | private final def _ivySettings
67 | private final def _ivyCoordinates
68 |
69 | private def _files
70 |
71 | IvyURLConnection(URL url, ivySettings, ivyCoordinates)
72 | {
73 | super(url)
74 | _ivySettings = ivySettings
75 | _ivyCoordinates = ivyCoordinates
76 | }
77 |
78 | public void connect()
79 | {
80 | AntUtils.withBuilder { ant ->
81 | def ivy = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.ivy.ant')
82 |
83 | GroovyIOUtils.withFile(_ivySettings) { File ivySettingsFile ->
84 | ivy.settings(file: ivySettingsFile)
85 |
86 | ivy.cachefileset(setid: 'fetchFromIvy',
87 | conf: _ivyCoordinates.size() == 4 ? _ivyCoordinates[3] : 'default',
88 | inline: true,
89 | organisation: _ivyCoordinates[0],
90 | module: _ivyCoordinates[1],
91 | revision: _ivyCoordinates[2])
92 |
93 | _files = ant.project.getReference('fetchFromIvy').collect { it.file }
94 | }
95 | }
96 | connected = true
97 | }
98 |
99 | void disconnect()
100 | {
101 | connected = false
102 | // nothing to do...
103 | }
104 |
105 | def getFiles()
106 | {
107 | return _files
108 | }
109 |
110 | public InputStream getInputStream()
111 | {
112 | if (!connected)
113 | connect()
114 |
115 | if(_files.size() != 1)
116 | {
117 | throw new IOException("not 1 artifact downloaded for ${_ivyCoordinates}: ${_files}")
118 | }
119 |
120 | return new FileInputStream(_files[0])
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/log/JulToSLF4jBridge.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | * Portions Copyright (c) 2013 Yan Pujante
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 | * use this file except in compliance with the License. You may obtain a copy of
7 | * 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, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | package org.linkedin.groovy.util.log
19 |
20 | import java.util.logging.LogManager
21 | import org.slf4j.bridge.SLF4JBridgeHandler
22 |
23 | /**
24 | * @author ypujante@linkedin.com
25 | */
26 | class JulToSLF4jBridge
27 | {
28 | /**
29 | * The problem with SLF4JBridgeHandler.install()
method is that it does not
30 | * remove the other handlers and as a result logs still make it the 'old' way.
31 | */
32 | synchronized static void installBridge()
33 | {
34 | if(!SLF4JBridgeHandler.isInstalled())
35 | {
36 | def rootLogger = LogManager.getLogManager().getLogger("")
37 |
38 | rootLogger.handlers.each {
39 | rootLogger.removeHandler(it)
40 | }
41 |
42 | rootLogger.addHandler(new SLF4JBridgeHandler())
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/log/MaskDataPatternConverter.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.groovy.util.log
18 |
19 | import org.apache.log4j.helpers.PatternConverter;
20 | import org.apache.log4j.spi.LoggingEvent
21 | import org.apache.log4j.spi.ThrowableInformation
22 | import java.util.regex.Pattern
23 | import java.util.regex.Matcher
24 |
25 | /**
26 | * @author mdubey@linkedin.com
27 | *
28 | * Created: Aug 2, 2010 1:32:04 PM
29 | */
30 | class MaskDataPatternConverter extends PatternConverter
31 | {
32 | boolean processThrowable
33 | def maskingMap
34 |
35 | public MaskDataPatternConverter(String maskingRegex, boolean processThrowable)
36 | {
37 | super();
38 | this.processThrowable = processThrowable
39 |
40 | // load the maskingRegex as a map
41 | if (maskingRegex) {
42 | GroovyShell groovysh = new GroovyShell()
43 | this.maskingMap = groovysh.evaluate(maskingRegex)
44 | // optimzation to store precompiled pattern in the map
45 | // def newMap = [:]
46 | // maskingMap.each { k, v ->
47 | // if(k instanceof String)
48 | // k = Pattern.compile(k)
49 | // newMap[k] = v
50 | // }
51 | // maskingMap = newMap
52 | }
53 | }
54 |
55 | @Override
56 | protected String convert(LoggingEvent event)
57 | {
58 | if (processThrowable) {
59 | ThrowableInformation information = event.getThrowableInformation()
60 | StringBuilder builder = new StringBuilder()
61 |
62 | if (information != null) {
63 | String[] stringRep = information.getThrowableStrRep()
64 |
65 | int length = stringRep.length;
66 | for (int i = 0; i < length; i++) {
67 | String string = stringRep[i]
68 | builder.append(maskSensitiveData(string)).append("\n")
69 | }
70 | }
71 | return builder.toString()
72 |
73 | } else {
74 | // convert message to filter out any encrypted data
75 | return maskSensitiveData(event.getRenderedMessage())
76 |
77 | }
78 |
79 | }
80 |
81 | private String maskSensitiveData(String message)
82 | {
83 | if (maskingMap) {
84 | maskingMap.each { entry ->
85 | def pat = entry.key
86 | Closure c = entry.value
87 | message = message.replaceAll(pat) { Object[] it ->
88 | def updated = c(it)
89 | return updated
90 | }
91 | }
92 | }
93 | return message
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/log/MaskDataPatternLayout.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.groovy.util.log
18 |
19 | import org.apache.log4j.PatternLayout
20 | import org.apache.log4j.helpers.PatternParser
21 |
22 | /**
23 | * Add support for filtering log message based on regex. This is mainly used to make sure we do not log sensitive information
24 | * in log files.
25 | *
26 | * This is achieved by adding a new option '%w' (inverted m) that processed the message for filtering. In log4j config MaskingRegex
27 | * should also be defined that contains these filters and actions as a groovy closure.
28 | *
29 | * Ex:
30 | *
31 | *
32 | *
33 | *
36 | *
42 | *
43 | *
44 | * @author mdubey@linkedin.com
45 | *
46 | * Created: Aug 2, 2010 12:57:15 PM
47 | */
48 | public class MaskDataPatternLayout extends PatternLayout {
49 |
50 | String maskingRegex;
51 |
52 | @Override
53 | public void activateOptions()
54 | {
55 | // This call on super forces a call to createPatternParser, which we need to get Parser setup correctly
56 | setConversionPattern(getConversionPattern())
57 | }
58 |
59 | @Override
60 | protected PatternParser createPatternParser(String pattern) {
61 | return new MaskDataPatternParser(pattern, getMaskingRegex());
62 | }
63 |
64 | public void setMaskingRegex(String maskingRegex)
65 | {
66 | this.maskingRegex = maskingRegex
67 | }
68 |
69 | public String getMaskingRegex()
70 | {
71 | return maskingRegex;
72 | }
73 |
74 | @Override
75 | public boolean ignoresThrowable()
76 | {
77 | return false;
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/log/MaskDataPatternParser.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.groovy.util.log
18 |
19 | import org.apache.log4j.helpers.PatternParser
20 |
21 | /**
22 | * @author mdubey@linkedin.com
23 | *
24 | * Created: Aug 2, 2010 1:29:10 PM
25 | */
26 | class MaskDataPatternParser extends PatternParser
27 | {
28 | private static final char MASKED_MESSAGE_CHAR = 'w' // looks like inverted m and is unused by PatternLayout
29 | private static final char MASKED_THROWABLE_CHAR = 's' // for use by printStacktrace
30 |
31 | private String maskingRegex
32 |
33 | public MaskDataPatternParser(String pattern, String maskingRegex) {
34 | super(pattern);
35 | this.maskingRegex = maskingRegex;
36 | }
37 |
38 | @Override
39 | protected void finalizeConverter(char c) {
40 | switch (c) {
41 | case MASKED_MESSAGE_CHAR:
42 | currentLiteral.setLength(0);
43 | addConverter(new MaskDataPatternConverter(maskingRegex, false));
44 | break;
45 | case MASKED_THROWABLE_CHAR:
46 | currentLiteral.setLength(0);
47 | addConverter(new MaskDataPatternConverter(maskingRegex, true));
48 | break;
49 | default:
50 | super.finalizeConverter(c);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/mop/GroovyMopUtils.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 |
18 | package org.linkedin.groovy.util.mop
19 |
20 | /**
21 | * This class contains utility methods for meta programming
22 | *
23 | * @author ypujante@linkedin.com
24 | */
25 | class GroovyMopUtils
26 | {
27 | /**
28 | * This method should be called from a missingMethod handler. It looks up a set of delegates
29 | * as an alternate for the method call (note that the order of the delegates matters). If a
30 | * delegate is found, it is automatically added as a new method to not have any penalty
31 | * with future calls
32 | */
33 | static def missingMethodDelegate(o, name, args, delegates)
34 | {
35 | // try to locate a delegate which can answer the call
36 | def delegate = delegates.find {it?.metaClass?.respondsTo(it, name, args) }
37 |
38 | if(delegate)
39 | {
40 | def methods = delegate.metaClass.respondsTo(delegate, name, args)
41 | // add the closure to o
42 | o.metaClass."${name}" << delegate.&"${name}"
43 | return methods[0].invoke(delegate, args)
44 | }
45 | else
46 | {
47 | throw new MissingMethodException("Unsupported call ${name}", o.class, args)
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/net/SingletonURLStreamHandlerFactory.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.groovy.util.net
18 |
19 | /**
20 | * The singleton of url stream handler (can register only 1 per VM).
21 | *
22 | * @author ypujante@linkedin.com */
23 | class SingletonURLStreamHandlerFactory implements URLStreamHandlerFactory
24 | {
25 | static SingletonURLStreamHandlerFactory INSTANCE = new SingletonURLStreamHandlerFactory()
26 |
27 | private final def _handlers = [:]
28 |
29 | public URLStreamHandler createURLStreamHandler(String protocol)
30 | {
31 | def handler
32 |
33 | synchronized(_handlers)
34 | {
35 | handler = _handlers[protocol]
36 | }
37 |
38 | if(!handler)
39 | return null
40 |
41 | if(handler instanceof Closure)
42 | return handler(protocol)
43 | else
44 | handler.createURLStreamHandler(protocol)
45 | }
46 |
47 | /**
48 | * Register a handler for the protocol
49 | */
50 | void registerHandler(String protocol, handler)
51 | {
52 | synchronized(_handlers)
53 | {
54 | if(_handlers[protocol])
55 | throw new IllegalStateException("already registered protocol ${protocol}".toString())
56 |
57 | _handlers[protocol] = handler
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/rest/RestException.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package org.linkedin.groovy.util.rest
18 |
19 | import org.linkedin.groovy.util.json.JsonUtils
20 |
21 | /**
22 | * Exception which will contain the original exception (which may not be available in this VM)...
23 | * @author ypujante@linkedin.com */
24 | class RestException extends Exception
25 | {
26 | private static final long serialVersionUID = 1L;
27 |
28 | public final String originalClassName
29 | public final String originalMessage
30 |
31 | RestException(String className, String message, StackTraceElement[] stackTrace)
32 | {
33 | super("class: ${className}, message: ${message}".toString())
34 | originalClassName = className
35 | originalMessage = message
36 | setStackTrace(stackTrace)
37 | }
38 |
39 | /**
40 | * From a json representation (as built by {@link #toJSON(Throwable)) builds a rest exception
41 | */
42 | static RestException fromJSON(jsonRepresentation)
43 | {
44 | def res = null
45 | def parent = null
46 | jsonRepresentation?.exception?.each { cause ->
47 | def ex = new RestException(cause.name, cause.message, rebuildStackTrace(cause.stackTrace))
48 | if(res == null)
49 | res = ex
50 | parent?.initCause(ex)
51 | parent = ex
52 | }
53 | return res
54 | }
55 |
56 | /**
57 | * 'Serializes' the throwable into a json representation in order to be able to rebuild it later.
58 | */
59 | static def toJSON(Throwable th)
60 | {
61 | if(th)
62 | {
63 | return JsonUtils.toJSON([exception: extractFullStackTrace(th, [])])
64 | }
65 | else
66 | return null
67 | }
68 |
69 | private static StackTraceElement[] rebuildStackTrace(stackTrace)
70 | {
71 | def elements = []
72 |
73 | stackTrace.each { ste ->
74 | elements << new StackTraceElement(ste.dc, ste.mn, ste.fn, ste.ln as int)
75 | }
76 |
77 | return elements as StackTraceElement[]
78 | }
79 |
80 | private static def extractFullStackTrace(exception, out)
81 | {
82 | if(exception)
83 | {
84 | out << [name: exception.getClass().name, message: exception.message, stackTrace: extractStackTrace(exception)]
85 | extractFullStackTrace(exception.cause, out)
86 | }
87 |
88 | return out
89 | }
90 |
91 | private static def extractStackTrace(exception)
92 | {
93 | def stackTrace = []
94 |
95 | exception?.stackTrace?.each { ste ->
96 | stackTrace << [dc: ste.className, mn: ste.methodName, fn: ste.fileName, ln: ste.lineNumber]
97 | }
98 |
99 | return stackTrace
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/groovy/org/linkedin/groovy/util/state/StateChangeListener.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 |
18 | package org.linkedin.groovy.util.state
19 |
20 | /**
21 | * The callback for state changes. The callback implementation should be lightweight.
22 | *
23 | * @author ypujante@linkedin.com
24 | */
25 | interface StateChangeListener
26 | {
27 | /**
28 | * On state change. Called only when the state (of the state machine) changes. It is called
29 | * with the new state (currentState/transitionState/error)
30 | */
31 | void onStateChange(oldState, newState)
32 | }
33 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/java/org/linkedin/util/json/jackson/JacksonPrettyPrinter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Yan Pujante
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | package org.linkedin.util.json.jackson;
17 |
18 | import com.fasterxml.jackson.core.JsonGenerator;
19 | import com.fasterxml.jackson.core.PrettyPrinter;
20 | import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
21 |
22 | import java.io.IOException;
23 |
24 | /**
25 | * Handles indentation levels + tighten output slightly
26 | *
27 | * @author yan@pongasoft.com
28 | */
29 | public class JacksonPrettyPrinter implements PrettyPrinter
30 | {
31 | public static final DefaultPrettyPrinter.Indenter LF_2_SPACES_INDENTER =
32 | new DefaultPrettyPrinter.Lf2SpacesIndenter();
33 |
34 | private final DefaultPrettyPrinter.Indenter _indenter;
35 | private int _nesting = 0;
36 |
37 | public JacksonPrettyPrinter(int indent)
38 | {
39 | super();
40 | if(indent == 2)
41 | _indenter = LF_2_SPACES_INDENTER;
42 | else
43 | _indenter = new LfNSpacesIndenter(indent);
44 | }
45 |
46 | @Override
47 | public void writeRootValueSeparator(JsonGenerator jg) throws IOException
48 | {
49 | }
50 |
51 | private void writeIndentation(JsonGenerator jg) throws IOException
52 | {
53 | _indenter.writeIndentation(jg, _nesting);
54 | }
55 |
56 | @Override
57 | public void writeStartObject(JsonGenerator jg) throws IOException
58 | {
59 | jg.writeRaw('{');
60 | _nesting++;
61 | }
62 |
63 | @Override
64 | public void writeEndObject(JsonGenerator jg, int nrOfEntries)
65 | throws IOException
66 | {
67 | _nesting--;
68 | writeIndentation(jg);
69 | jg.writeRaw('}');
70 | }
71 |
72 | @Override
73 | public void writeObjectEntrySeparator(JsonGenerator jg)
74 | throws IOException
75 | {
76 | jg.writeRaw(',');
77 | writeIndentation(jg);
78 | }
79 |
80 | @Override
81 | public void writeObjectFieldValueSeparator(JsonGenerator jg)
82 | throws IOException
83 | {
84 | jg.writeRaw(": ");
85 | }
86 |
87 | @Override
88 | public void writeStartArray(JsonGenerator jg) throws IOException
89 | {
90 | jg.writeRaw('[');
91 | _nesting++;
92 | }
93 |
94 | @Override
95 | public void writeEndArray(JsonGenerator jg, int nrOfValues)
96 | throws IOException
97 | {
98 | _nesting--;
99 | writeIndentation(jg);
100 | jg.writeRaw(']');
101 | }
102 |
103 | @Override
104 | public void writeArrayValueSeparator(JsonGenerator jg) throws IOException
105 | {
106 | jg.writeRaw(',');
107 | writeIndentation(jg);
108 | }
109 |
110 | @Override
111 | public void beforeArrayValues(JsonGenerator jg) throws IOException
112 | {
113 | writeIndentation(jg);
114 | }
115 |
116 | @Override
117 | public void beforeObjectEntries(JsonGenerator jg) throws IOException
118 | {
119 | writeIndentation(jg);
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/main/java/org/linkedin/util/json/jackson/LfNSpacesIndenter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Yan Pujante
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 | package org.linkedin.util.json.jackson;
17 |
18 | import com.fasterxml.jackson.core.JsonGenerator;
19 | import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
20 |
21 | import java.io.IOException;
22 | import java.util.Arrays;
23 |
24 | /**
25 | * Copied/adapted from jackson to handle N spaces instead of 2
26 | *
27 | * @author yan@pongasoft.com
28 | */
29 | public class LfNSpacesIndenter implements DefaultPrettyPrinter.Indenter
30 | {
31 | private final int _numSpaces;
32 |
33 | /**
34 | * Constructor
35 | */
36 | public LfNSpacesIndenter(int numSpaces)
37 | {
38 | if(numSpaces <= 0)
39 | throw new IllegalArgumentException(numSpaces + " must be > 0");
40 |
41 | _numSpaces = numSpaces;
42 | }
43 |
44 | final static String SYSTEM_LINE_SEPARATOR;
45 |
46 | static
47 | {
48 | String lf = null;
49 | try
50 | {
51 | lf = System.getProperty("line.separator");
52 | }
53 | catch(Throwable t)
54 | {
55 | t.printStackTrace(System.err);
56 | } // access exception?
57 | SYSTEM_LINE_SEPARATOR = (lf == null) ? "\n" : lf;
58 | }
59 |
60 | final static int SPACE_COUNT = 64;
61 | final static char[] SPACES = new char[SPACE_COUNT];
62 |
63 | static
64 | {
65 | Arrays.fill(SPACES, ' ');
66 | }
67 |
68 | @Override
69 | public boolean isInline()
70 | {
71 | return false;
72 | }
73 |
74 | @Override
75 | public void writeIndentation(JsonGenerator jg, int level)
76 | throws IOException
77 | {
78 | jg.writeRaw(SYSTEM_LINE_SEPARATOR);
79 | // N spaces per level
80 | int numSpaces;
81 | // faster to add than multiply...
82 | switch(_numSpaces)
83 | {
84 | case 1:
85 | numSpaces = level;
86 | break;
87 |
88 | case 2:
89 | numSpaces = level + level;
90 | break;
91 |
92 | case 3:
93 | numSpaces = level + level + level;
94 | break;
95 |
96 | case 4:
97 | numSpaces = level + level + level + level;
98 | break;
99 |
100 | default:
101 | numSpaces = level * _numSpaces;
102 | break;
103 | }
104 |
105 | while(numSpaces > SPACE_COUNT)
106 | { // should never happen but...
107 | jg.writeRaw(SPACES, 0, SPACE_COUNT);
108 | numSpaces -= SPACES.length;
109 | }
110 | jg.writeRaw(SPACES, 0, numSpaces);
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/org.linkedin.util-groovy/src/test/groovy/test/util/collections/TestGroovyCollectionsUtils.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | package test.util.collections
18 |
19 | import org.linkedin.groovy.util.collections.GroovyCollectionsUtils
20 |
21 | /**
22 | * @author ypujante@linkedin.com */
23 | class TestGroovyCollectionsUtils extends GroovyTestCase
24 | {
25 | public void testMap()
26 | {
27 | assertTrue(GroovyCollectionsUtils.compareIgnoreType((Map) null, (Map) null))
28 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(null, [:]))
29 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([:], null))
30 | assertTrue(GroovyCollectionsUtils.compareIgnoreType([:], [:]))
31 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([a: null], [b: null]))
32 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([a: 1], [b: null]))
33 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new LinkedHashMap([a: 200, b: 21]), new TreeMap([a: 200, b: 21])))
34 | }
35 |
36 | public void testList()
37 | {
38 | assertTrue(GroovyCollectionsUtils.compareIgnoreType((List) null, (List) null))
39 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(null, []))
40 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([], null))
41 | assertTrue(GroovyCollectionsUtils.compareIgnoreType([], []))
42 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([1], [null]))
43 | assertFalse(GroovyCollectionsUtils.compareIgnoreType([null], [1]))
44 | assertTrue(GroovyCollectionsUtils.compareIgnoreType([1,2,3], [1,2,3]))
45 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new ArrayList([1,2,3]), new Vector([1,2,3])))
46 | }
47 |
48 | public void testSet()
49 | {
50 | assertTrue(GroovyCollectionsUtils.compareIgnoreType((Set) null, (Set) null))
51 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(null, new HashSet()))
52 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(new HashSet(), null))
53 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new HashSet(), new HashSet()))
54 | assertFalse(GroovyCollectionsUtils.compareIgnoreType(new HashSet([1]), new HashSet()))
55 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new HashSet([1,2,3]), new HashSet([1,2,3])))
56 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(new HashSet([3,2,1]), new LinkedHashSet([2,3,1])))
57 | }
58 |
59 | public void testCollection()
60 | {
61 | assertTrue(GroovyCollectionsUtils.compareContent((Collection) null, (Collection) null))
62 | assertFalse(GroovyCollectionsUtils.compareContent((Collection) null, new HashSet()))
63 | assertFalse(GroovyCollectionsUtils.compareContent(new HashSet(), (Collection) null))
64 | assertTrue(GroovyCollectionsUtils.compareContent(new HashSet(), new ArrayList()))
65 | assertFalse(GroovyCollectionsUtils.compareContent(new HashSet([1]), new ArrayList()))
66 | assertTrue(GroovyCollectionsUtils.compareContent(new HashSet([1,2,3]), [1,2,3]))
67 | assertTrue(GroovyCollectionsUtils.compareContent([3,2,1], new LinkedHashSet([2,3,1])))
68 | assertTrue(GroovyCollectionsUtils.compareContent([3,2,1], [1,2,3]))
69 | }
70 |
71 | public void testFlatten()
72 | {
73 | def src =
74 | [
75 | k1: 'v1',
76 | k2:
77 | [
78 | k21: 'v21',
79 | k22: ['v221', 'v222']
80 | ],
81 | k3: ['v31', ['v321', 'v322'], [k33: 'v33']],
82 | k4: [],
83 | k5: [:],
84 | k6: ['v61', [], [:], 'v64']
85 | ]
86 |
87 | def expected = [
88 | k1: 'v1',
89 | 'k2.k21': 'v21',
90 | 'k2.k22[0]': 'v221',
91 | 'k2.k22[1]': 'v222',
92 | 'k3[0]': 'v31',
93 | 'k3[1][0]': 'v321',
94 | 'k3[1][1]': 'v322',
95 | 'k3[2].k33': 'v33',
96 | 'k6[0]': 'v61',
97 | 'k6[3]': 'v64'
98 | ]
99 |
100 | assertTrue(GroovyCollectionsUtils.compareIgnoreType(expected, GroovyCollectionsUtils.flatten(src)))
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/project-spec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010-2010 LinkedIn, Inc
3 | * Portions Copyright (c) 2011-2013 Yan Pujante
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 | * use this file except in compliance with the License. You may obtain a copy of
7 | * 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, WITHOUT
13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 | * License for the specific language governing permissions and limitations under
15 | * the License.
16 | */
17 |
18 | spec = [
19 | name: 'linkedin-utils',
20 | group: 'org.linkedin',
21 | version: '1.9.0',
22 |
23 | versions: [
24 | groovy: '2.0.7',
25 | jackson: '2.1.4',
26 | slf4j: '1.6.2' // to be compatible with grails 2.2.1
27 | ],
28 |
29 | // information about the build framework itself
30 | build: [
31 | type: "gradle",
32 | commands: [
33 | "snapshot": "gradlew xxx",
34 | "release": "gradlew -Prelease=true xxx"
35 | ]
36 | ]
37 | ]
38 |
39 | spec.scmUrl = "git@github.com:linkedin/${spec.name}.git"
40 |
41 | /**
42 | * External dependencies
43 | */
44 | spec.external = [
45 | ant: 'org.apache.ant:ant:1.8.2',
46 | groovy: "org.codehaus.groovy:groovy-all:${spec.versions.groovy}",
47 | json: 'org.json:json:20090211',
48 | jacksoncore: "com.fasterxml.jackson.core:jackson-core:${spec.versions.jackson}",
49 | jacksondatabind: "com.fasterxml.jackson.core:jackson-databind:${spec.versions.jackson}",
50 | junit: 'junit:junit:4.10',
51 | log4j: 'log4j:log4j:1.2.16',
52 | slf4j: "org.slf4j:slf4j-api:${spec.versions.slf4j}",
53 | slf4jLog4j: "org.slf4j:slf4j-log4j12:${spec.versions.slf4j}",
54 | slf4jJul: "org.slf4j:jul-to-slf4j:${spec.versions.slf4j}"
55 | ]
56 |
--------------------------------------------------------------------------------
/repositories.gradle:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Copyright (c) 2010-2010 LinkedIn, Inc
4 | * Portions Copyright (c) 2013 Yan Pujante
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7 | * use this file except in compliance with the License. You may obtain a copy of
8 | * 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, WITHOUT
14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 | * License for the specific language governing permissions and limitations under
16 | * the License.
17 | */
18 |
19 | def topReleaseDir = new File(userConfig.top.release.dir ?: "${topBuildDir}/release").canonicalFile
20 | def topPublishDir = new File(userConfig.top.publish.dir ?: "${topBuildDir}/publish").canonicalFile
21 |
22 | /**
23 | * Repositories for build
24 | */
25 | allRepositories.build = {
26 | add(new org.apache.ivy.plugins.resolver.FileSystemResolver()) {
27 | name = "build-release"
28 | addIvyPattern "${topReleaseDir}/[organisation]/[module]/[revision]/[module]-[revision].ivy"
29 | addArtifactPattern "${topReleaseDir}/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
30 | m2compatible = true
31 | checkmodified = true
32 | }
33 |
34 | mavenRepo name: 'build-publish', url: topPublishDir.toURI()
35 |
36 | mavenCentral()
37 | }
38 |
39 | /**
40 | * Repositories for buildScript
41 | */
42 | allRepositories.buildscript = allRepositories.build
43 |
44 | /**
45 | * Repositories for release
46 | */
47 | allRepositories.snapshotRelease = {
48 | add(new org.apache.ivy.plugins.resolver.FileSystemResolver()) {
49 | name = 'local-release'
50 | addIvyPattern "${topReleaseDir}/[organisation]/[module]/[revision]/[module]-[revision].ivy"
51 | addArtifactPattern "${topReleaseDir}/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
52 | m2compatible = true
53 | }
54 | }
55 |
56 | allRepositories.release = allRepositories.snapshotRelease
57 |
58 | /**
59 | * Repositories for publish
60 | */
61 | allRepositories.snapshotPublish = {
62 | mavenDeployer {
63 | repository(url: "file://localhost${topPublishDir}")
64 | pom.whenConfigured { pomToConfigure ->
65 | pomToConfigure.project {
66 | name project.name
67 | description 'Set of utility classes used by other LinkedIn open source projects'
68 | url 'http://github.com/linkedin/linkedin-utils'
69 | licenses {
70 | license {
71 | name 'The Apache Software License, Version 2.0'
72 | url 'http://www.apache.org/licenses/LICENSE-2.0'
73 | }
74 | }
75 | developers {
76 | developer {
77 | id 'ypujante'
78 | name 'Yan Pujante'
79 | email 'yan@pongasoft.com'
80 | }
81 | developer {
82 | id 'mdubey'
83 | name 'Manish Dubey'
84 | email 'mdubey@linkedin.com'
85 | }
86 | }
87 | scm {
88 | connection "scm:git:${spec.scmUrl}"
89 | developerConnection "scm:git:${spec.scmUrl}"
90 | url spec.scmUrl
91 | }
92 | }
93 | }
94 | }
95 | }
96 |
97 | allRepositories.publish = allRepositories.snapshotPublish
98 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2010 LinkedIn, Inc
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | */
16 |
17 | include ':org.linkedin.util-core',
18 | ':org.linkedin.util-groovy'
--------------------------------------------------------------------------------