/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.jackrabbit.core.cluster;
import java.io.ByteArrayInputStream;
import java.io.CharArrayReader;
import org.apache.jackrabbit.core.journal.JournalException;
import org.apache.jackrabbit.core.journal.Record;
import org.apache.jackrabbit.core.xml.ClonedInputSource;
import org.xml.sax.InputSource;
/**
* Record for propagating workspace modifications across the cluster. Currently
* only workspace creation is propagated because workspace deletion is not yet
* implemented.
*/
public class WorkspaceRecord extends ClusterRecord {
/**
* Identifier: NAMESPACE.
*/
static final char IDENTIFIER = 'W';
/**
* Subtype for determining workspace action.
*/
public static final int CREATE_WORKSPACE_ACTION_TYPE = 1;
/**
* Base workspace action
*/
public abstract static class Action {
abstract int getType();
abstract void write(Record record) throws JournalException;
abstract void read(Record record) throws JournalException;
}
/**
* Action for workspace creation.
*/
static final class CreateWorkspaceAction extends Action {
private InputSource inputSource;
private char[] charArray;
private byte[] byteArray;
@Override
int getType() {
return CREATE_WORKSPACE_ACTION_TYPE;
}
CreateWorkspaceAction() {
}
CreateWorkspaceAction(ClonedInputSource inputSource) {
this.inputSource = inputSource;
this.charArray = inputSource.getCharacterArray();
this.byteArray = inputSource.getByteArray();
}
@Override
void write(Record record) throws JournalException {
// store the input source
record.writeString(inputSource.getEncoding());
record.writeString(inputSource.getPublicId());
record.writeString(inputSource.getSystemId());
// save character array if present
if (charArray != null) {
record.writeBoolean(true);
record.writeString(new String(charArray));
} else {
record.writeBoolean(false);
}
// save the bytearray if present
if (byteArray != null) {
record.writeBoolean(true);
record.writeInt(byteArray.length);
record.write(byteArray);
} else {
record.writeBoolean(false);
}
}
@Override
void read(Record record) throws JournalException {
// restore the input source
inputSource = new InputSource();
inputSource.setEncoding(record.readString());
inputSource.setPublicId(record.readString());
inputSource.setSystemId(record.readString());
if (record.readBoolean()) {
charArray = record.readString().toCharArray();
inputSource.setCharacterStream(new CharArrayReader(charArray));
}
if (record.readBoolean()) {
final int size = record.readInt();
byteArray = new byte[size];
record.readFully(byteArray);
inputSource.setByteStream(new ByteArrayInputStream(byteArray));
}
}
public InputSource getInputSource() {
return inputSource;
}
}
// current action
private Action action;
/**
* Creates a new {@link WorkspaceRecord} for create workspace action.
*
* @param workspace
* workspace name
* @param inputSource
* input source with configuration for the workspace
* @param record
* journal record
*/
protected WorkspaceRecord(String workspace, ClonedInputSource inputSource,
Record record) {
super(record, workspace);
action = new CreateWorkspaceAction(inputSource);
}
/**
* Creates a new empty {@link WorkspaceRecord}.
*
* @param record
*/
protected WorkspaceRecord(Record record) {
super(record);
}
@Override
protected void doRead() throws JournalException {
workspace = record.readString();
// determine type
int action = record.readInt();
if (action == CREATE_WORKSPACE_ACTION_TYPE) {
this.action = new CreateWorkspaceAction();
}
if (this.action != null) {
this.action.read(record);
} else {
throw new JournalException("Unknown workspace action type");
}
}
@Override
protected void doWrite() throws JournalException {
record.writeChar(IDENTIFIER);
record.writeString(workspace);
// store the type
record.writeInt(getActionType());
if (action != null) {
action.write(record);
} else {
throw new JournalException("Can not write empty workspace action");
}
}
public int getActionType() {
return action != null ? action.getType() : -1;
}
public CreateWorkspaceAction getCreateWorkspaceAction() {
return (CreateWorkspaceAction) action;
}
@Override
public void process(ClusterRecordProcessor processor) {
processor.process(this);
}
}