blob: 067c238b6e398639129978f3dce3be21ac3c63e3 [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.core.ext.linker;
import com.google.gwt.core.ext.Linker;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.util.Util;
import com.google.gwt.util.tools.Utility;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* An artifact that will be emitted into the output. All EmittedArtifacts
* contained in the {@link ArtifactSet} at the end of the Linking process will
* be emitted by the compiler into the module's output directory. This type may
* be extended by Linker providers to provide alternative implementations of
* {@link #getContents(TreeLogger)}.
*
* TODO(bobv): provide a timestamp so we can make the time on output files match
* that of input files?
*/
public abstract class EmittedArtifact extends Artifact<EmittedArtifact> {
/**
* Describes the visibility of an artifact.
*/
public enum Visibility {
/**
* A public artifact is something that may be served to clients.
*/
Public,
/**
* A private artifact is something that is only used during the build
* process.
*/
Private {
@Override
public boolean matches(Visibility visibility) {
switch (visibility) {
case LegacyDeploy:
case Private:
return true;
default:
return false;
}
}
},
/**
* A deploy artifact is deployed to the server but is never served to the
* client.
*/
Deploy {
@Override
public boolean matches(Visibility visibility) {
switch (visibility) {
case Deploy:
case LegacyDeploy:
return true;
default:
return false;
}
}
},
/**
* For legacy use only - used for artifacts that were previously marked as
* private because they should not be delivered to the client, but actually
* should be visible to the server. These artifacts will now be treated as
* both Private and Deploy, so that existing build tools that expect to find
* them in the output directory for Private artifacts will find them.
*
* New code should use Deploy instead.
*/
LegacyDeploy {
@Override
public boolean matches(Visibility visibility) {
switch (visibility) {
case Deploy:
case LegacyDeploy:
case Private:
return true;
default:
return false;
}
}
};
/**
* Returns true if this visibility matches the requested visibility level,
* dealing with the fact that {@link #LegacyDeploy} matches both
* {@link #Private} and {@link #Deploy}.
*
* @param visibility
* @return true if this visibility matches the requested level
*/
public boolean matches(Visibility visibility) {
return this == visibility;
}
}
private final String partialPath;
/**
* This is mutable because it has no effect on identity.
*/
private Visibility visibility;
protected EmittedArtifact(Class<? extends Linker> linker, String partialPath) {
super(linker);
assert partialPath != null;
this.partialPath = partialPath;
visibility = Visibility.Public;
}
/**
* Provides access to the contents of the EmittedResource.
*/
public abstract InputStream getContents(TreeLogger logger)
throws UnableToCompleteException;
/**
* Returns the time, measured in milliseconds from the epoch, at which the
* Artifact was last modified. This will be used to set the last-modified
* timestamp on the files written to disk.
* <p>
* The default implementation always returns the current time. Subclasses
* should override this method to provide a type-appropriate value.
*
* @return the time at which the Artifact was last modified
*/
public long getLastModified() {
return System.currentTimeMillis();
}
/**
* Returns the partial path within the output directory of the
* EmittedArtifact.
*/
public final String getPartialPath() {
return partialPath;
}
/**
* @return the visibility
*/
public Visibility getVisibility() {
return visibility;
}
@Override
public final int hashCode() {
return getPartialPath().hashCode();
}
/**
* Returns whether or not the data contained in the EmittedArtifact should be
* written into the module output directory or into an auxiliary directory.
* <p>
* EmittedArtifacts that return <code>true</code> for this method will not
* be emitted into the normal module output location, but will instead be
* written into a directory that is a sibling to the module output directory.
* The partial path of the EmittedArtifact will be prepended with the
* short-name of the Linker type that created the EmittedArtifact.
* <p>
* Private EmittedArtifacts are intended for resources that generally should
* not be deployed to the server in the same location as the module
* compilation artifacts.
*
* @deprecated use {@link #getVisibility()} instead
*/
@Deprecated
public boolean isPrivate() {
return visibility == Visibility.Private;
}
/**
* Sets the private attribute of the EmittedResource.
*
* @param isPrivate true if this artifact is private
*
* @deprecated use {@link #setVisibility(Visibility)} instead
*/
@Deprecated
public void setPrivate(boolean isPrivate) {
this.visibility = isPrivate ? Visibility.Private : Visibility.Public;
}
/**
* @param visibility the visibility to set
*/
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
}
@Override
public String toString() {
return getPartialPath();
}
/**
* Provides access to the contents of the EmittedResource.
*/
public void writeTo(TreeLogger logger, OutputStream out)
throws UnableToCompleteException {
try {
InputStream in = getContents(logger);
Util.copyNoClose(in, out);
Utility.close(in);
} catch (IOException e) {
logger.log(TreeLogger.ERROR, "Unable to read or write stream", e);
throw new UnableToCompleteException();
}
}
@Override
protected final int compareToComparableArtifact(EmittedArtifact o) {
return getPartialPath().compareTo(o.getPartialPath());
}
@Override
protected final Class<EmittedArtifact> getComparableArtifactType() {
return EmittedArtifact.class;
}
}