/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* 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 org.onebusaway.presentation.impl.resources;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.regex.Pattern;
import org.w3c.css.sac.InputSource;
import org.w3c.css.sac.Parser;
import com.google.gwt.resources.client.CssResource;
import com.steadystate.css.parser.SACParserCSS2;
public class CssResourceImpl extends ResourcePrototypeImpl implements
CssResource, ResourceWithUrl, LocalResource, InvocationHandler {
static Pattern URL_PATTERN = Pattern.compile("^@url (\\w+) (\\w+);$");
private URL _cssUrl;
private File _outputFile;
private String _outputText;
private String _outputUrl;
public CssResourceImpl(ClientBundleContext context,
ClientBundleImpl parentBundle, String name, URL cssUrl) {
super(context, parentBundle, name);
_cssUrl = cssUrl;
}
/****
* {@link CssResource} Interface
****/
@Override
public boolean ensureInjected() {
// This method has no effect, as we do not support dynamic injection
return false;
}
@Override
public String getText() {
refresh();
return _outputText;
}
/****
* {@link ResourceWithUrl}
****/
@Override
public String getUrl() {
refresh();
return _outputUrl;
}
/****
* {@link InvocationHandler} Interface
****/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Class<?> declaringClass = method.getDeclaringClass();
if( declaringClass.isAssignableFrom(CssResourceImpl.class))
return method.invoke(this, args);
String name = method.getName();
int index = name.lastIndexOf('.');
if( index != -1)
name = name.substring(index+1);
return name;
}
/*****************************************************************************
* Private Methods
****************************************************************************/
protected synchronized void refresh() {
if (isUpToDate())
return;
System.out.println("refreshing resource: " + _cssUrl);
try {
_outputText = parse();
String key = ResourceSupport.getHash(_outputText);
_outputUrl = constructURL(key, "css", this);
_outputFile = new File(_context.getTempDir(), cleanUrlForPath(_outputUrl));
_localUrl = _outputFile.toURI().toURL();
File parent = _outputFile.getParentFile();
if (parent != null && !parent.exists())
parent.mkdirs();
BufferedWriter writer = new BufferedWriter(new FileWriter(_outputFile));
writer.write(_outputText);
writer.close();
setUpToDate();
} catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
private String parse() throws IOException {
InputStreamReader reader2 = new InputStreamReader(_cssUrl.openStream());
InputSource source2 = new InputSource(reader2);
Parser p = new SACParserCSS2();
CssDocumentHandlerImpl handler = new CssDocumentHandlerImpl(_context,
_parentBundle);
p.setDocumentHandler(handler);
p.parseStyleSheet(source2);
reader2.close();
return handler.getResults();
}
private String cleanUrlForPath(String url) {
url = url.replace('?', '_');
return url;
}
}