blob: 9a10bdfe07744b85e8152c2cf9c96a94d7b5d7d3 [file] [log] [blame]
# Copyright 2013, Big Switch Networks, Inc.
#
# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
# the following special exception:
#
# LOXI Exception
#
# As a special exception to the terms of the EPL, you may distribute libraries
# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
# that copyright and licensing notices generated by LoxiGen are not altered or removed
# from the LoxiGen Libraries and the notice provided below is (i) included in
# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
# documentation for the LoxiGen Libraries, if distributed in binary form.
#
# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
#
# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
# a copy of the EPL at:
#
# http://www.eclipse.org/legal/epl-v10.html
#
# 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
# EPL for the specific language governing permissions and limitations
# under the EPL.
"""
@brief Main Java Generation module
"""
import logging
import pdb
import os
import shutil
import loxi_globals
from loxi_ir import *
import lang_java
import test_data
from collections import namedtuple
from import_cleaner import ImportCleaner
import template_utils
import loxi_utils.loxi_utils as loxi_utils
import java_gen.java_model as java_model
logger = logging.getLogger(__name__)
def gen_all_java(install_dir):
basedir= '%s/openflowj' % install_dir
logger.info("Outputting to %s" % basedir)
if os.path.exists(basedir):
shutil.rmtree(basedir)
os.makedirs(basedir)
copy_prewrite_tree(basedir)
gen = JavaGenerator(basedir, JavaGeneratorOptions(instrument=True))
gen.create_of_interfaces()
gen.create_of_classes()
gen.create_of_const_enums()
gen.create_of_factories()
JavaGeneratorOptions = namedtuple("JavaGeneratorOptions", ("instrument",))
class JavaGenerator(object):
templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
def __init__(self, basedir, gen_opts):
self.basedir = basedir
self.java_model = java_model.model
self.gen_opts = gen_opts
def render_class(self, clazz, template, src_dir=None, **context):
if not src_dir:
src_dir = "gen-src/main/java/"
context['class_name'] = clazz.name
context['package'] = clazz.package
context['template_dir'] = self.templates_dir
context['genopts']= self.gen_opts
filename = os.path.join(self.basedir, src_dir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
dirname = os.path.dirname(filename)
if not os.path.exists(dirname):
os.makedirs(dirname)
prefix = '//::(?=[ \t]|$)'
logger.debug("rendering filename: %s" % filename)
with open(filename, "w") as f:
template_utils.render_template(f, template, [self.templates_dir], context, prefix=prefix)
try:
cleaner = ImportCleaner(filename)
cleaner.find_used_imports()
cleaner.rewrite_file(filename)
except:
logger.info('Cannot clean imports from file %s' % filename)
def create_of_const_enums(self):
for enum in self.java_model.enums:
if enum.name in ["OFPort"]:
continue
self.render_class(clazz=enum,
template='const.java', enum=enum, all_versions=self.java_model.versions)
for version in enum.versions:
clazz = java_model.OFGenericClass(package="org.projectfloodlight.openflow.protocol.ver{}".format(version.dotless_version), name="{}SerializerVer{}".format(enum.name, version.dotless_version))
if enum.is_bitmask:
self.render_class(clazz=clazz, template="const_set_serializer.java", enum=enum, version=version)
else:
self.render_class(clazz=clazz, template="const_serializer.java", enum=enum, version=version)
def create_of_interfaces(self):
""" Create the base interfaces for of classes"""
for interface in self.java_model.interfaces:
#if not utils.class_is_message(interface.c_name):
# continue
self.render_class(clazz=interface,
template="of_interface.java", msg=interface)
def create_of_classes(self):
""" Create the OF classes with implementations for each of the interfaces and versions """
for interface in self.java_model.interfaces:
for java_class in interface.versioned_classes:
if self.java_model.generate_class(java_class):
if not java_class.is_virtual:
self.render_class(clazz=java_class,
template='of_class.java', version=java_class.version, msg=java_class,
impl_class=java_class.name)
self.create_unit_test(java_class.unit_test)
else:
disc = java_class.discriminator
if disc:
self.render_class(clazz=java_class,
template='of_virtual_class.java', version=java_class.version, msg=java_class,
impl_class=java_class.name, model=self.java_model)
else:
logger.warn("Class %s virtual but no discriminator" % java_class.name)
else:
logger.info("Class %s ignored by generate_class" % java_class.name)
def create_unit_test(self, unit_tests):
if unit_tests.has_test_data:
for i in range(unit_tests.length):
unit_test = unit_tests.get_test_unit(i)
if unit_test.has_test_data:
self.render_class(clazz=unit_test,
template='unit_test.java', src_dir="gen-src/test/java",
version=unit_test.java_class.version,
test=unit_test, msg=unit_test.java_class,
test_data=unit_test.test_data)
def create_of_factories(self):
for factory in self.java_model.of_factories:
self.render_class(clazz=factory, template="of_factory_interface.java", factory=factory)
for factory_class in factory.factory_classes:
self.render_class(clazz=factory_class, template="of_factory_class.java", factory=factory_class, model=self.java_model)
self.render_class(clazz=java_model.OFGenericClass(package="org.projectfloodlight.openflow.protocol", name="OFFactories"), template="of_factories.java", versions=self.java_model.versions)
def copy_prewrite_tree(basedir):
""" Recursively copy the directory structure from ./java_gen/pre-write
into $basedir"""
logger.info("Copying pre-written files into %s" % basedir)